基于windows系统,使用c语言完成一对一的socket客户端与服务器程序,并解决recv和send函数的阻塞问题,可以让程序同时进行收发通信
时间: 2024-02-27 12:51:46 浏览: 115
以下是一个基于Windows系统、使用C语言的一对一Socket客户端和服务器程序,采用非阻塞的方式进行收发通信。注意:本示例仅供参考,实际使用中需要根据具体情况进行修改。
服务器端代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib") // 链接 ws2_32.dll 库
int main() {
// 初始化 Winsock
WSADATA wsaData;
int ret = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (ret != 0) {
printf("WSAStartup failed: %d\n", ret);
return 1;
}
// 创建套接字
SOCKET serverSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serverSock == INVALID_SOCKET) {
printf("socket failed: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
// 绑定地址和端口
SOCKADDR_IN serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); // 任意IP地址
serverAddr.sin_port = htons(12345); // 端口号为 12345
ret = bind(serverSock, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
if (ret == SOCKET_ERROR) {
printf("bind failed: %d\n", WSAGetLastError());
closesocket(serverSock);
WSACleanup();
return 1;
}
// 监听连接请求
ret = listen(serverSock, SOMAXCONN);
if (ret == SOCKET_ERROR) {
printf("listen failed: %d\n", WSAGetLastError());
closesocket(serverSock);
WSACleanup();
return 1;
}
printf("Waiting for client...\n");
// 接受客户端连接
SOCKADDR_IN clientAddr;
int addrLen = sizeof(clientAddr);
SOCKET clientSock = accept(serverSock, (SOCKADDR*)&clientAddr, &addrLen);
if (clientSock == INVALID_SOCKET) {
printf("accept failed: %d\n", WSAGetLastError());
closesocket(serverSock);
WSACleanup();
return 1;
}
printf("Client connected: %s:%d\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
// 设置套接字为非阻塞模式
u_long nonBlockingMode = 1;
ret = ioctlsocket(clientSock, FIONBIO, &nonBlockingMode);
if (ret == SOCKET_ERROR) {
printf("ioctlsocket failed: %d\n", WSAGetLastError());
closesocket(clientSock);
closesocket(serverSock);
WSACleanup();
return 1;
}
// 接收和发送数据
char recvBuf[1024];
char sendBuf[1024];
while (1) {
// 接收数据
int recvLen = recv(clientSock, recvBuf, sizeof(recvBuf), 0);
if (recvLen == SOCKET_ERROR) {
int errCode = WSAGetLastError();
if (errCode == WSAEWOULDBLOCK) {
// 没有数据可读,继续等待
continue;
} else {
printf("recv failed: %d\n", errCode);
break;
}
} else if (recvLen == 0) {
// 客户端已关闭连接
printf("Client disconnected.\n");
break;
}
// 处理接收到的数据
// ...
// 发送数据
int sendLen = send(clientSock, sendBuf, strlen(sendBuf), 0);
if (sendLen == SOCKET_ERROR) {
int errCode = WSAGetLastError();
if (errCode == WSAEWOULDBLOCK) {
// 发送缓冲区已满,继续等待
continue;
} else {
printf("send failed: %d\n", errCode);
break;
}
}
// 处理发送完成的数据
// ...
}
// 关闭套接字
closesocket(clientSock);
closesocket(serverSock);
// 清理 Winsock
WSACleanup();
return 0;
}
```
客户端代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib") // 链接 ws2_32.dll 库
int main() {
// 初始化 Winsock
WSADATA wsaData;
int ret = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (ret != 0) {
printf("WSAStartup failed: %d\n", ret);
return 1;
}
// 创建套接字
SOCKET clientSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (clientSock == INVALID_SOCKET) {
printf("socket failed: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
// 连接服务器
SOCKADDR_IN serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // IP地址为本地
serverAddr.sin_port = htons(12345); // 端口号为 12345
ret = connect(clientSock, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
if (ret == SOCKET_ERROR) {
printf("connect failed: %d\n", WSAGetLastError());
closesocket(clientSock);
WSACleanup();
return 1;
}
printf("Connected to server.\n");
// 设置套接字为非阻塞模式
u_long nonBlockingMode = 1;
ret = ioctlsocket(clientSock, FIONBIO, &nonBlockingMode);
if (ret == SOCKET_ERROR) {
printf("ioctlsocket failed: %d\n", WSAGetLastError());
closesocket(clientSock);
WSACleanup();
return 1;
}
// 接收和发送数据
char recvBuf[1024];
char sendBuf[1024];
while (1) {
// 发送数据
int sendLen = send(clientSock, sendBuf, strlen(sendBuf), 0);
if (sendLen == SOCKET_ERROR) {
int errCode = WSAGetLastError();
if (errCode == WSAEWOULDBLOCK) {
// 发送缓冲区已满,继续等待
continue;
} else {
printf("send failed: %d\n", errCode);
break;
}
}
// 处理发送完成的数据
// ...
// 接收数据
int recvLen = recv(clientSock, recvBuf, sizeof(recvBuf), 0);
if (recvLen == SOCKET_ERROR) {
int errCode = WSAGetLastError();
if (errCode == WSAEWOULDBLOCK) {
// 没有数据可读,继续等待
continue;
} else {
printf("recv failed: %d\n", errCode);
break;
}
} else if (recvLen == 0) {
// 服务器已关闭连接
printf("Server disconnected.\n");
break;
}
// 处理接收到的数据
// ...
}
// 关闭套接字
closesocket(clientSock);
// 清理 Winsock
WSACleanup();
return 0;
}
```
阅读全文