解释这段代码逐句给出解释并注释#pragma warningdisable4996#include winsock2h#include stdioh#include stdlibh#include windowsh#include iostream#include string#include stringh#define msg_Length 100#define NUMBER 256#prag
这段代码是一个使用Winsock2库实现的简单聊天室服务器程序,以下是逐句的解释和注释:
#pragma warning(disable:4996) //禁用指定警告,具体指的是4996,这个警告是关于使用不安全的函数的警告
#include <winsock2.h> //Winsock2.h是Windows Sockets API的头文件,为开发网络应用程序提供了底层的接口
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include
#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;
} //主函数,实现了服务器的初始化、监听、接受连接等功
原文地址: https://www.cveoy.top/t/topic/eGQy 著作权归作者所有。请勿转载和采集!