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实现

不会,再补。