这段代码是一个使用Winsock2库实现的简单聊天室服务器程序,以下是逐句的解释和注释:

#pragma warning(disable:4996) //禁用指定警告,具体指的是4996,这个警告是关于使用不安全的函数的警告

#include <winsock2.h> //Winsock2.h是Windows Sockets API的头文件,为开发网络应用程序提供了底层的接口

#include <stdio.h> #include <stdlib.h> #include <windows.h> #include #include #include <string.h> //各种头文件,包括标准库、Windows API、C++库等

#define msg_Length 100 #define NUMBER 256 //定义两个宏,msg_Length表示消息长度,NUMBER表示最大连接数

#pragma comment(lib,"WS2_32.lib") //告诉编译器链接WS2_32.lib库,这个库包含了Winsock2的实现代码

using namespace std; //使用std命名空间

int snum = 0;//建立的套接字数量 int SOCKETS[NUMBER];//套接字们

int Q[10];//存放群组信息 int q = 0;//群组数量 string names[10]; //所有注册用户的姓名 int u = 0;//user数量

HANDLE Process[NUMBER];//线程数组

//线程执行 DWORD WINAPI processing(LPVOID e) { int chat_socket = ((int)e); //将void类型的指针e转换为int类型的指针,再取出其中的值,赋值给chat_socket int str_len = 0, i; char msg[msg_Length]; char u_msg[msg_Length]; //定义两个字符数组,用于存放消息和回复消息

while ((str_len = recv(chat_socket, msg, sizeof(msg), 0)) != -1) {
//接收客户端发来的消息,recv函数会返回接收到的字节数
    if (msg[0] == '#') {
    //通过信息头判断消息类型是昵称
        int fla = 1;
        cout << "查询姓名信息" << msg << endl;
        //与服务器端数据比较,检验是否已经存在的昵称
        for (int o = 0; o < 10; o++) {
            string p = names[o];
            if (p == msg) {
                fla = 0;//存在的话就标识一下
                break;
            }
        }

        if (fla == 0) {
        //如果存在,发出错误识别码,告知客户端已经存在这个昵称了
            sprintf(u_msg, "@%s", msg);//@:昵称已经存在
            //sprintf是C语言中的格式化输出函数,将格式化后的字符串写入数组u_msg中
            for (int i = 0; i < snum; i++)
                send(SOCKETS[i], msg, str_len, 0);
            //将消息发送给所有的客户端
        }
        else {
            char b[20] = { "" };
            strcpy(b, msg); //昵称不存在则存档
            //将msg字符串复制到b数组中
            names[u] = b;//存入数据中
            u++;
            sprintf(u_msg, "*%s", msg);//*:告知客户端昵称可以使用 
            for (int i = 0; i < snum; i++)
                send(SOCKETS[i], msg, str_len, 0);
            //将消息发送给所有的客户端
        }
    }
    else if (msg[0] == '(' && msg[1] == 'G' && msg[2] == 'r') {
    //判断消息类型是群组信息
        cout << "建立群组:" << msg[6] << endl;
        for (int i = 0; i < snum; i++)
            send(SOCKETS[i], msg, str_len, 0);
        cout << "转发群组代号\n";
    }
    else if (msg[0] == 'q' && msg[1] == 'u' && msg[2] == 'n') {
    //判断消息类型是查询群组信息
        cout << "核对群组信息" << msg[3] << endl;
        for (int u = 0; u < 10; u++) {
            if (msg[3] == Q[u]) {
                sprintf(msg, "GE");
                for (int i = 0; i < snum; i++)
                    send(SOCKETS[i], msg, str_len, 0);
                break;
            }
        }
        Q[q] = msg[3];
        q++;
    }
    else if (msg[0] == 'j' && msg[1] == 'o' && msg[2] == 'i') {
    //判断消息类型是加入群组
        cout << "核对群组信息" << msg[3] << endl;
        int flag = 0;
        for (int u = 0; u < 10; u++) {
            //cout<<"!@"<<Q[u]<<endl;
            if (msg[3] == Q[u]) {
                flag = 1;
                break;
            }
        }
        if (flag == 1) {
            sprintf(msg, "GY");//GY群组存在
            for (int i = 0; i < snum; i++)
                send(SOCKETS[i], msg, str_len, 0);
        }
        else {
            sprintf(msg, "GN");//GN群组不存在
            for (int i = 0; i < snum; i++)
                send(SOCKETS[i], msg, str_len, 0);
        }
    }
    else {
        for (int i = 0; i < snum; i++)
            send(SOCKETS[i], msg, str_len, 0);
        cout << "群发成功" << endl;
    }
    //如果不是以上三种情况,则直接将消息群发给所有的客户端
}

printf("客户端退出:%d\n", GetCurrentThreadId());

for (i = 0; i < snum; i++) {
    if (chat_socket == SOCKETS[i]) {
        while (i++ < snum - 1)
            SOCKETS[i] = SOCKETS[i + 1];
        break;
    }
}
snum--;
// 关闭同客户端的连接
closesocket(chat_socket);
return -1;

}

int main() { for (int y = 0; y < 10; y++) { names[y] = "xxx";//初始化昵称 } //初始化WSA WSADATA wsaData; WORD banben = MAKEWORD(2, 2); WSAStartup(banben, &wsaData); //请求socket

//创建套接字
SOCKET serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serv_sock == INVALID_SOCKET) {
    cout << "连接失败" << endl;
    WSACleanup();
    exit(1);
}

//sockaddr
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(8888);//端口设置
sin.sin_addr.S_un.S_addr = INADDR_ANY;    //本地地址

//将套接字绑定到地址 
if (bind(serv_sock, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR) {
    cout << "套接字绑定失败" << endl;
    WSACleanup();
    exit(1);
}

//监听
if (listen(serv_sock, NUMBER) == SOCKET_ERROR) {
    cout << "端口监听失败" << endl;
    WSACleanup();
    exit(1);
}
cout << "开始监听:" << endl;
sockaddr_in addr;
int nAddrLen = sizeof(addr);
DWORD clientID;//此线程的id句柄,用于标记用户
SOCKET chat_socket;

while (1) {
    cout << "等待新连接" << endl;
    // 接受一个新连接
    chat_socket = accept(serv_sock, (SOCKADDR*)&addr, &nAddrLen);
    if (chat_socket == INVALID_SOCKET) {
        cout << "接收失败" << endl;
        continue;
    }
    Process[snum] = CreateThread(NULL, 0, processing, (void*)&chat_socket, 0, &clientID);
    //参数:安全性、堆栈大小(默认)、线程函数、函数参数、执行延迟、线程ID--返回值 
    SOCKETS[snum++] = chat_socket;
    cout << "接收到来自" << inet_ntoa(addr.sin_addr) << "的连接" << endl;
}

for (int i = 0; i < snum; i++) {
    CloseHandle(Process[i]);
}
// 关闭监听套节字
closesocket(serv_sock);
// 释放WSA
WSACleanup();
return 0;

} //主函数,实现了服务器的初始化、监听、接受连接等功

解释这段代码逐句给出解释并注释#pragma warningdisable4996#include winsock2h#include stdioh#include stdlibh#include windowsh#include iostream#include string#include stringh#define msg_Length 100#define NUMBER 256#prag

原文地址: https://www.cveoy.top/t/topic/eGQy 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录