리셋 되지 말자

websocket client, socket server source code 본문

websocket

websocket client, socket server source code

kyeongjun-dev 2020. 4. 21. 16:44

client.html

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
</head>
<body>
    <form>
        <!-- 서버로 메시지를 보낼 텍스트 박스 -->
        <input id="textMessage" type="text">
        <!-- 전송 버튼 -->
        <input onclick="sendMessage()" value="Send" type="button">
        <!-- 접속 종료 버튼 -->
        <input onclick="disconnect()" value="Disconnect" type="button">
    </form>
    <br />
    <!-- 출력 area -->
    <textarea id="messageTextArea" rows="10" cols="50"></textarea>
    <script type="text/javascript">
        // 웹 서버를 접속한다.
        var webSocket = new WebSocket("ws://IP주소:8785");
        // 웹 서버와의 통신을 주고 받은 결과를 출력할 오브젝트를 가져옵니다.
        var messageTextArea = document.getElementById("messageTextArea");

        // 소켓 접속이 되면 호출되는 함수
        webSocket.onopen = function(message){
            messageTextArea.value += "Server connect...\n";
        };

        // 소켓 접속이 끝나면 호출되는 함수
        webSocket.onclose = function(message){
            messageTextArea.value += "Server Disconnect...\n";
        };

        // 소켓 통신 중에 에러가 발생되면 호출되는 함수
        webSocket.onerror = function(message){
            messageTextArea.value += "error...\n";
        };

        // 소켓 서버로 부터 메시지가 오면 호출되는 함수.
        webSocket.onmessage = function(message){
            // 출력 area에 메시지를 표시한다.
            messageTextArea.value += "Recieve From Server => "+message.data+"\n";
        };

        // 서버로 메시지를 전송하는 함수
        function sendMessage(){
            var message = document.getElementById("textMessage");
            messageTextArea.value += "Send to Server => "+message.value+"\n";
            //웹소켓으로 textMessage객체의 값을 보낸다.
            webSocket.send(message.value);
            //textMessage객체의 값 초기화
            message.value = "";
        };

        function disconnect(){
            //disconnect버튼을 누르면 웹소켓 접속을 종료
            webSocket.close();
        };
    </script>
</body>
</html>

server.py

import socket
import sys
import re
import hashlib
import base64
import threading
import struct
import subprocess
import os
def send(client, msg):
    print('\n' + '\x81' + '\n')
    data = bytearray(msg.encode('utf-8'))
    if len(data) > 126:
        data = bytearray([129, 126]) + bytearray(struct.pack('>H', len(data))) + data
    else:
        data = bytearray([129, len(data)]) + data
    client.send(data)
    print("**********************************")
    #print(data)
    print("**********************************")

def recv(client):
    first_byte = bytearray(client.recv(1))[0]
    FIN = (0xFF & first_byte) >> 7
    opcode = (0x0F & first_byte)
    second_byte = bytearray(client.recv(1))[0]
    mask = (0xFF & second_byte) >> 7
    payload_len = (0x7F & second_byte)
    if opcode < 3:
        if (payload_len == 126):
            payload_len = struct.unpack_from('>H', bytearray(client.recv(2)))[0]
        elif (payload_len == 127):
            payload_len = struct.unpack_from('>Q', bytearray(client.recv(8)))[0]
        if mask == 1:
            masking_key = bytearray(client.recv(4))
        masked_data = bytearray(client.recv(payload_len))
        if mask == 1:
            data = [masked_data[i] ^ masking_key[i%4] for i in range(len(masked_data))]
        else:
            data = masked_data
    else:
        return opcode, bytearray(b'\x00')
    return opcode, bytearray(data)

def handshake(client):
    request = client.recv(2048)
    p=re.compile('Sec-WebSocket-Key: (.*)\\r')
    m = p.search(request.decode())

    key = m.group(1)+'258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
    #key = 'dGhlIHNhbXBsZSBub25jZQ=='+'258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
    h=hashlib.sha1()
    h.update(key.encode())

    sh1_key = hashlib.sha1().digest()
    base64_key = base64.b64encode(h.digest())
    print(base64_key.decode())

    response = "HTTP/1.1 101 Switching Protocols\r\n"+\
           "Upgrade: websocket\r\n"+\
           "Connection: Upgrade\r\n"+\
           "Sec-WebSocket-Accept: %s\r\n"+\
           "\r\n"
    r = response % (base64_key).decode()
    print(r)

    client.send(r.encode())

    #여기까지 됨


def handle_client (client, addr):
    print("dknfkelkdnkfnldf")
    handshake(client)
    try:
        while 1:
            opcode, data = recv(client)
            if opcode == 0x8:
                print ('close frame received')
                break
            elif opcode == 0x1:
                if len(data) == 0:
                    break
                msg = data.decode('utf-8', 'ignore')
                send(client, msg)
                try:
                    os.chdir('..')
                    output = str(subprocess.check_output(msg, stderr=subprocess.STDOUT, shell=True), 'cp949')
                    print(output)
                except subprocess.CalledProcessError as cpe:
                    output = str(cpe.output, 'cp949')
                print(output)
                send(client, output)
            else:
                print('frame not handled : opcode=' + str(opcode) + ' len=' + str(len(data)))

    except Exception as e:
        print(str(e))
    print("disconnected")
    client.close()

def start_server (port):
    sock = socket.socket()
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(('IP주소', port))
    sock.listen(1)
    while True:
        print('Waiting for connection on port ...' )
        client, addr = sock.accept()
        print('Connection from: ' + str(addr))
        threading.Thread(target = handle_client, args = (client, addr)).start()


start_server(8785)

python3.7 버전으로 동작하는걸 확인 하였고, python에서 필요한 패키지를 설치한 후 실행하고 나서 웹 브라우저로 html코드를 실행시키면 connect... 라는 문구가 뜨면서 연결된다. server.py를 윈도우에서 실행 시켰을 경우에, client에서 dir을 입력하면, cmd에서 dir 명령어를 친 결과를 서버에서 보내서 client의 textarea에 출력해준다.

IP주소라고 입력되어 있는 곳에 server pc의 ip주소를 입력해주면 된다.

'websocket' 카테고리의 다른 글

websocket을 이용한 python server에 대용량 파일 전송하기  (0) 2020.05.06
[websocket] Sec-WebSocket-Key 변환  (0) 2020.04.12
websocket 공부  (0) 2020.04.10
websocket 상세 설명 글  (0) 2020.04.10
Comments