1. 程式人生 > >【Python 聊天室】socket

【Python 聊天室】socket

# reference:
# https://www.cnblogs.com/JohnABC/p/6076006.html
# https://www.cnblogs.com/maociping/p/5132583.html

from socket import *
from select import *
class Socket():
    def __init__(self, host, port):
        self.host = host
        self.port = port
        self.bufsize = 1024
        self.addr = (host, port)

        self.tcpSerSock = socket(AF_INET, SOCK_STREAM)  # 建立套接字
        self.tcpSerSock.bind(self.addr) # 繫結地址和埠號
        self.tcpSerSock.listen(5) # 套接字等待連結的client個數上限是5

        self.epoll_instance = epoll()
        self.epoll_instance.register(self.tcpSerSock.fileno(),EPOLLIN|EPOLLET) 
        # 注:EPOLLIN(可讀),EPOLLOUT(可寫),
        # EPOLLET: 邊緣觸發模式(只通知一次),EPOLLLT:水平觸發模式(通知後沒有做處理的話還會繼續通知)

        self.s_dict = {}    # 儲存連線客戶端編號的字典

    def accept(self):
        while True:
            self.epoll_list = self.epoll_instance.poll() # 輪詢註冊的事件集合,返回值為[(檔案控制代碼,對應的事件),(...),....]
            for fd,event in self.epoll_list:
                if fd == self.tcpSerSock.fileno():  # 如果活動socket為當前伺服器socket,表示有新連線
                    cs,userinfo = self.tcpSerSock.accept()
                    self.epoll_instance.register(cs.fileno(),EPOLLIN|EPOLLET)
                    self.s_dict[cs.fileno()] = cs
                else:
                    cs = self.s_dict[fd]
                    recv_data = cs.recv(1024)
                    print(recv_data.decode('UTF-8'))
                    if len(recv_data) > 0 :
                        cs.send(recv_data)
                    else:
                        print('adsfasdf')
                        self.epoll_instance.unregister(fd)
                        cs.close()
                        self.s_dict.pop(fd)


if __name__ == '__main__':
    socketx = Socket('127.0.0.1', 8080)
    socketx.accept()