我想多个客户端都可以连接上服务器并且每个客户端都可以多次打字并且其中一个客户端发到消息另外几个客户端也能接受的到消息
时间: 2023-08-03 17:29:13 浏览: 103
一个服务器对多个客户端双方可互通信息
4星 · 用户满意度95%
了解了您的需求后,您需要对服务器端代码进行以下修改:
1. 对于每个连接到服务器的客户端,创建一个新的线程来处理该客户端的消息。
2. 为了让多个客户端都能连接到服务器,您需要将服务器端的 `accept` 函数放到一个循环中,以便能够接受多个客户端的连接请求。
3. 当服务器收到某个客户端的消息时,需要将该消息转发给所有连接到服务器的客户端。
下面是修改后的服务器端代码,您可以参考一下:
```c
#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")
SOCKET g_clientSockets[10];
int g_clientCount = 0;
DWORD WINAPI ClientThread(LPVOID lpParam)
{
SOCKET clientSocket = *(SOCKET*)lpParam;
char recvBuf[50], sendBuf[50];
while (1) {
// 接收客户端消息并处理
int ret = recv(clientSocket, recvBuf, 50, 0);
if (ret <= 0) {
break;
}
printf("Received message from client: %s\n", recvBuf);
// 转发消息给所有客户端
for (int i = 0; i < g_clientCount; i++) {
if (g_clientSockets[i] != clientSocket) {
send(g_clientSockets[i], recvBuf, strlen(recvBuf) + 1, 0);
}
}
}
// 关闭客户端套接字
closesocket(clientSocket);
// 从全局变量中移除该客户端套接字
for (int i = 0; i < g_clientCount; i++) {
if (g_clientSockets[i] == clientSocket) {
g_clientCount--;
memmove(&g_clientSockets[i], &g_clientSockets[i + 1], (g_clientCount - i) * sizeof(SOCKET));
break;
}
}
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_family = AF_INET;
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrSrv.sin_port = htons(6000);
bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
// 开始监听客户端连接请求
listen(sockSrv, 5);
while (1) {
// 接受客户端连接并处理消息
SOCKADDR_IN addrClient;
int len = sizeof(SOCKADDR);
SOCKET sockConn = accept(sockSrv, (SOCKADDR*)&addrClient, &len);
// 将新连接的客户端套接字加入全局变量
g_clientSockets[g_clientCount++] = sockConn;
// 创建新线程来处理该客户端的消息
HANDLE hThread = CreateThread(NULL, 0, ClientThread, &sockConn, 0, NULL);
// 关闭线程句柄
CloseHandle(hThread);
}
closesocket(sockSrv);
WSACleanup();
return 0;
}
```
同时,您还需要对客户端代码进行修改,以便让它能够接收其他客户端发送过来的消息。下面是修改后的客户端代码,您可以参考一下:
```c
#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;
}
```
请注意,上述代码中仅为示例代码,可能还需要您根据实际情况进行一些修改。
阅读全文