下面是使用 C 语言分别实现 TCP 客户端的阻塞式接收和非阻塞式接收的示例代码。
1. 阻塞式接收
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int sock;
struct sockaddr_in server_addr;
char buffer[BUFFER_SIZE];
// 创建 socket
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
// 设置服务器地址
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
// 将IPv4地址从文本转换为二进制形式
if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) {
perror("Invalid address / Address not supported");
exit(EXIT_FAILURE);
}
// 与服务器连接
if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Connection failed");
exit(EXIT_FAILURE);
}
// 阻塞式接收数据
while (1) {
ssize_t bytes_received = recv(sock, buffer, BUFFER_SIZE - 1, 0);
if (bytes_received < 0) {
perror("Receive failed");
break;
} else if (bytes_received == 0) {
printf("Server closed the connection.\n");
break;
}
buffer[bytes_received] = '\0'; // null-terminate the string
printf("Received: %s\n", buffer);
}
close(sock);
return 0;
}
2. 非阻塞式接收
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <fcntl.h> // for fcntl()
#include <errno.h>
#define PORT 8080
#define BUFFER_SIZE 1024
int main() {
int sock;
struct sockaddr_in server_addr;
char buffer[BUFFER_SIZE];
// 创建 socket
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
// 设置服务器地址
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
// 将IPv4地址从文本转换为二进制形式
if(inet_pton(AF_INET,"127.0.0.1",&server_addr.sin_addr)<=0){
perror("Invalid address / Address not supported");
exit(EXIT_FAILURE);
}
// 与服务器连接
if(connect(sock,(struct sockaddr*)&server_addr,sizeof(server_addr))<0){
perror("Connection failed");
exit(EXIT_FAILURE);
}
// 设置socket为非阻塞模式
int flags = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flags | O_NONBLOCK);
while (1) {
ssize_t bytes_received = recv(sock, buffer, BUFFER_SIZE - 1 ,MSG_DONTWAIT);
if (bytes_received > 0) {
buffer[bytes_received] = '\0';
printf("Received: %s\n", buffer);
} else if (bytes_received == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
perror("Receive failed");
break;
}
usleep(100000); // Sleep for a short duration to avoid busy waiting
}
close(sock);
}
注意事项:
- 确保在运行这些客户端程序之前,目标主机上有一个 TCP 服务在监听指定的端口(例如使用相同的 IP 地址和端口号)。
- 在非阻塞模式下,
recv()
返回EAGAIN
或EWOULDBLOCK
错误码表示没有数据可读。在这种情况下,需要继续循环或者采取其他措施。 - 上述示例中使用了简化的错误处理,实际应用中可以根据需求增强异常处理和资源管理。
内容由零声教学AI助手提供,问题来源于学员提问