#define _WINSOCK_DEPRECATED_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #include <WinSock2.h> #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 #endif #pragma comment(lib, "ws2_32.lib") #define MAX_CLIENTS 10 #define MAX_BUFFER_SIZE 50 SOCKET clientSockets[MAX_CLIENTS]; // 客户端套接字数组 int numClients = 0; // 客户端数量 DWORD WINAPI ClientThread(LPVOID lpParam) { SOCKET clientSocket = *(SOCKET*)lpParam; char recvBuf[MAX_BUFFER_SIZE]; while (1) { int ret = recv(clientSocket, recvBuf, MAX_BUFFER_SIZE, 0); if (ret <= 0) { break; } // 将消息广播给所有客户端 for (int i = 0; i < numClients; i++) { send(clientSockets[i], recvBuf, strlen(recvBuf) + 1, MSG_NOSIGNAL); } } // 客户端断开连接,从套接字数组中移除 for (int i = 0; i < numClients; i++) { if (clientSockets[i] == clientSocket) { for (int j = i; j < numClients - 1; j++) { clientSockets[j] = clientSockets[j + 1]; } break; } } numClients--; closesocket(clientSocket); return 0; } int main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(1, 1); err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { return -1; } if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); return -1; } SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(6000); bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); listen(sockSrv, 5); printf("服务器已启动,等待客户端连接...\n"); while (1) { SOCKADDR_IN addrClient; int len = sizeof(SOCKADDR); SOCKET sockConn = accept(sockSrv, (SOCKADDR*)&addrClient, &len); printf("客户端 %s:%d 已连接\n", inet_ntoa(addrClient.sin_addr), ntohs(addrClient.sin_port)); // 将新的客户端套接字添加到数组中 clientSockets[numClients++] = sockConn; // 创建线程处理客户端消息 HANDLE hThread = CreateThread(NULL, 0, ClientThread, &sockConn, 0, NULL); CloseHandle(hThread); } closesocket(sockSrv); WSACleanup(); return 0; }
时间: 2024-04-25 12:26:38 浏览: 131
这是一个基于WinSock2的简单的C语言聊天室服务器程序,可以实现多个客户端之间的信息广播。程序中使用了socket、bind、listen、accept等函数来创建服务器套接字、绑定端口、监听连接请求、接受连接等操作。当有客户端连接时,会将新的客户端套接字添加到客户端套接字数组中,并创建一个新的线程来处理客户端发送的消息。当有客户端发送消息时,服务器会将消息广播给所有的客户端。
程序中的宏定义可以忽略不计,主要作用是消除编译器的警告信息。其中,_WINSOCK_DEPRECATED_NO_WARNINGS宏用于忽略WinSock2废弃的函数的警告,_CRT_SECURE_NO_WARNINGS宏用于忽略使用不安全函数的警告。
在程序的主函数中,首先通过WSAStartup函数初始化WinSock2库,然后创建服务器套接字,绑定端口并开始监听连接请求。当有客户端连接时,会将新的客户端套接字添加到客户端套接字数组中,然后创建一个新的线程来处理客户端发送的消息。在客户端线程中,通过recv函数接收客户端发送的消息,并将消息广播给所有的客户端。当客户端断开连接时,会从客户端套接字数组中移除该套接字,并关闭套接字。
总的来说,这是一个简单的C语言聊天室服务器程序,可以作为学习网络编程的入门案例。需要注意的是,这个程序没有进行任何的安全验证和错误处理,只是为了演示基本的网络编程技术。在实际应用中,需要根据具体的需求进行改进和完善。
相关问题
#include "stdafx.h" #define _WINSOCK_DEPRECATED_NO_WARNINGS #include <Winsock2.h> #include <stdio.h> #include <stdlib.h> #define DEFAULT_PORT 5050 //服务端默认端口 #pragma comment(lib, "wsock32.lib")什么意思
这段代码主要是实现了一个基于 Winsock2 库的服务端程序,其中:
- `#include "stdafx.h"` 是用来包含预编译头文件的指令。
- `#define _WINSOCK_DEPRECATED_NO_WARNINGS` 定义了一个宏,表示不使用已经过时的 Winsock API。
- `#include <Winsock2.h>` 是包含 Winsock2 库的头文件。
- `#include <stdio.h>` 和 `#include <stdlib.h>` 是标准 C 库头文件,用于输入/输出和内存管理等操作。
- `#define DEFAULT_PORT 5050` 定义了一个常量,表示服务端程序的默认端口号为 5050。
- `#pragma comment(lib, "wsock32.lib")` 是指定连接 Winsock 库时需要使用的库文件。
综上,这段代码主要是为了支持服务端程序通过 Winsock2 库实现网络通信,其中包含了 Winsock2 库的头文件和库文件,并定义了一些常量和宏来实现网络通信。
客户端代码#define _WINSOCK_DEPRECATED_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #include <WinSock2.h> #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 #endif #pragma comment(lib,"ws2_32.lib") DWORD WINAPI ReceiveThread(LPVOID lpParam) { SOCKET sockClient = (SOCKET)lpParam; char recvBuf[50]; while (1) { // 接收服务器的消息并打印出来 int ret = recv(sockClient, recvBuf, 50, 0); if (ret <= 0) { break; } printf("Received from server: %s\n", recvBuf); } return 0; } int main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(1, 1); err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { return -1; } if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { WSACleanup(); return -1; } // 创建套接字并连接到服务器 SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(6000); connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); // 创建新线程来接收服务器的消息 HANDLE hThread = CreateThread(NULL, 0, ReceiveThread, &sockClient, 0, NULL); char sendBuf[50]; while (1) { // 读取用户输入的消息并发送给服务器 printf("Input message to send: "); fgets(sendBuf, 50, stdin); send(sockClient, sendBuf, strlen(sendBuf) + 1, 0); } // 关闭线程句柄 CloseHandle(hThread); closesocket(sockClient); WSACleanup(); return 0; }
这段代码是一个简单的客户端代码,主要功能是连接服务器,并发送和接收消息。它也使用了 WinSock2 库来进行网络编程。在主函数中,首先调用了 WSACleanup() 函数来释放 WinSock2 库占用的资源。然后创建了一个套接字,并将其连接到服务器。接着创建一个新线程来接收服务器的消息,使用 fgets() 函数读取用户输入的消息,并将其发送给服务器。在 ReceiveThread 函数中,不断接收服务器发送的消息,并打印出来。当服务器断开连接时,该线程退出。在主函数中,当用户输入 exit 命令时,关闭线程句柄,释放套接字并释放 WinSock2 库占用的资源。
阅读全文