用C语言与Winsock完成一对多Socket客户端和用户端程序,消息发送与接收不会阻塞,同时支持多个用户端
时间: 2024-02-05 16:12:55 浏览: 68
基于WinSocket编程的客户端和服务器端通信程序
实现一对多通信需要使用TCP/IP协议,Winsock库提供了相应的API函数来实现网络通信。以下是一个简单的基于Winsock的TCP/IP客户端和服务器端程序的示例代码,可以实现多个客户端连接到服务器并发送消息,同时服务器可以向所有客户端广播消息。
服务器端代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib") //加载 ws2_32.dll
#define PORT 8888 //服务器监听端口号
int main()
{
WSADATA wsaData;
SOCKET serverSocket, clientSocket;
SOCKADDR_IN serverAddr, clientAddr;
int addrLen = sizeof(SOCKADDR_IN);
char recvBuf[1024];
int recvLen;
char sendBuf[1024];
int sendLen;
int i;
int clientCount = 0;
SOCKET clientSockets[10];
//初始化Winsock库
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("WSAStartup failed!\n");
return 1;
}
//创建套接字
serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serverSocket == INVALID_SOCKET)
{
printf("socket failed!\n");
WSACleanup();
return 1;
}
//绑定套接字到本地地址和端口
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddr.sin_port = htons(PORT);
if (bind(serverSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
{
printf("bind failed!\n");
closesocket(serverSocket);
WSACleanup();
return 1;
}
//监听连接请求
if (listen(serverSocket, SOMAXCONN) == SOCKET_ERROR)
{
printf("listen failed!\n");
closesocket(serverSocket);
WSACleanup();
return 1;
}
printf("Server started, waiting for clients...\n");
while (1)
{
//接受连接请求
clientSocket = accept(serverSocket, (SOCKADDR*)&clientAddr, &addrLen);
if (clientSocket == INVALID_SOCKET)
{
printf("accept failed!\n");
continue;
}
//将客户端套接字加入数组
clientSockets[clientCount] = clientSocket;
clientCount++;
//打印客户端地址和端口号
printf("Client %s:%d connected.\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
//向所有客户端广播有新客户端连接
sprintf(sendBuf, "Client %s:%d connected.", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
for (i = 0; i < clientCount - 1; i++)
{
sendLen = send(clientSockets[i], sendBuf, strlen(sendBuf) + 1, 0);
}
}
//关闭所有客户端套接字
for (i = 0; i < clientCount; i++)
{
closesocket(clientSockets[i]);
}
//关闭服务器套接字
closesocket(serverSocket);
//清理Winsock库
WSACleanup();
return 0;
}
```
客户端代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib") //加载 ws2_32.dll
#define SERVER_IP "127.0.0.1" //服务器IP地址
#define PORT 8888 //服务器监听端口号
int main()
{
WSADATA wsaData;
SOCKET clientSocket;
SOCKADDR_IN serverAddr;
char recvBuf[1024];
int recvLen;
char sendBuf[1024];
int sendLen;
//初始化Winsock库
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("WSAStartup failed!\n");
return 1;
}
//创建套接字
clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (clientSocket == INVALID_SOCKET)
{
printf("socket failed!\n");
WSACleanup();
return 1;
}
//连接到服务器
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = inet_addr(SERVER_IP);
serverAddr.sin_port = htons(PORT);
if (connect(clientSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
{
printf("connect failed!\n");
closesocket(clientSocket);
WSACleanup();
return 1;
}
//向服务器发送消息
sprintf(sendBuf, "Hello from client %d.", GetCurrentProcessId());
sendLen = send(clientSocket, sendBuf, strlen(sendBuf) + 1, 0);
//接收服务器消息
recvLen = recv(clientSocket, recvBuf, sizeof(recvBuf), 0);
printf("Received from server: %s\n", recvBuf);
//关闭套接字
closesocket(clientSocket);
//清理Winsock库
WSACleanup();
return 0;
}
```
以上代码只是基础示例,还需要进行错误处理和优化。同时如果要支持多个客户端,可以使用线程或者IOCP模型来处理多个客户端的连接和消息传输。
阅读全文