python_socket实现
# -*- coding = utf-8 -*- # @Time : 2021/8/14 11:49 # @Author : 刘卓文 # @File : 聊天室.py # @Software : PyCharm import socket import threading import datetime import logging class ChatServer: def __init__(self,ip,port): self.addr =(ip,port) #定义addr存放ip和端口 self.sock = socket.socket() #套接字赋一个0.0.0.0 0的新值, self.cilents = {} #创建一个字典容器 self.event = threading.Event() def start(self): self.sock.bind(self.addr) #绑定ip和端口,直是赋值,但是还没有绑定 self.sock.listen() #绑定已赋值的套接字 threading.Thread(target=self.accept,name='accept').start() def accept(self): while not self.event.is_set(): s,raddr = self.sock.accept() #阻塞1,等待对面的端口连接,accept赋值自己的端口,以及对端raddr地址和端口号 self.cilents[raddr] = s threading.Thread(target=self.recv,name='recv',args=(s, )).start() def recv(self,sock): while not self.event.is_set(): #服务器通过recv方法来接受数据 try: data = sock.recv(1024) except Exception as e: logging.error(e) data = quit if data==b'quit': self.cilents.pop(sock.getpeername()) sock.close() break msg = "{} {} {}".format(sock.getpeername(),datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S"),data.decode()).encode() #服务器通过send发送响应 for s in self.cilents.values(): s.send(msg) #给现存的每一个端口放送数据 def stop(self): for s in self.clients.values: s.close() self.sock.close() self.event.set() cs = ChatServer('127.0.0.1',9999) cs.start() while True: cmd = input(">>>") if cmd.strip() == 'quit': cs.stop() threading.Event.wait(3) # break
c++实现
#include <winsock2.h> // winsock2的头文件 #include <iostream> #pragma comment(lib, "ws2_32.lib") using namespace std; // stdcall的线程处理函数 DWORD WINAPI ThreadFun(LPVOID lpThreadParameter); int main() { WSADATA wd; if (WSAStartup(MAKEWORD(2, 2), &wd) != 0) { cout << "WSAStartup Error:" << WSAGetLastError() << endl; return 0; } //第一步:数据初始化 // 1. 创建流式套接字 SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (s == INVALID_SOCKET) { cout << "socket error:" << WSAGetLastError() << endl; return 0; } // 2. 绑定端口和ip sockaddr_in addr; memset(&addr, 0, sizeof(sockaddr_in)); addr.sin_family = AF_INET; addr.sin_port = htons(8000); addr.sin_addr.s_addr = INADDR_ANY; int len = sizeof(sockaddr_in); if (bind(s, (SOCKADDR*)&addr, len) == SOCKET_ERROR) { cout << "bind Error:" << WSAGetLastError() << endl; return 0; } // 3. 监听 listen(s, 5); //第二步:进行accept() // 主线程循环接收客户端的连接 while (true) { sockaddr_in addrClient; len = sizeof(sockaddr_in); // 4.接受成功返回与client通讯的Socket SOCKET c = accept(s, (SOCKADDR*)&addrClient, &len); if (c != INVALID_SOCKET) { // 创建线程,并且传入与client通讯的套接字 HANDLE hThread = CreateThread(NULL, 0, ThreadFun, (LPVOID)c, 0, NULL); CloseHandle(hThread); // 关闭对线程的引用 } } // 清理winsock2的环境 WSACleanup(); return 0; } //第三步与客户端进行交互 DWORD WINAPI ThreadFun(LPVOID lpThreadParameter) { // 5.与客户端通讯,发送或者接受数据 SOCKET c = (SOCKET)lpThreadParameter; cout << "欢迎" << c << "进入聊天室!" << endl; // 发送数据 char buf[100] = { 0 }; sprintf(buf, "欢迎 %d 进入聊天室!",int(c)); send(c, buf, 100, 0); // 循环接收客户端数据 int ret = 0; do { char buf2[100] = { 0 }; ret = recv(c, buf2, 100, 0); cout << c << " 说:" << buf2 << endl; } while (ret != SOCKET_ERROR && ret != 0); cout << c << "离开了聊天室!"; return 0; }
mfc实现
不会,再补。