Linux下TCP连接,send错误代码32-管道破裂

问题描述:今天写程序,socket后send出现这个问题,send的返回值为-1,而errno为32,这个错误代码为broken pipe,即管道破裂。

问题形成原因:后来通过排查研究,发现出现该种问题出现的可能性为以下两种:

1.socket失败,与服务器端的链接没有成功,从而管道破裂。

2.服务端将客户端的socket断开,一样造成这样的问题。

此时这样的程序收到broken pipe的信号,会自动退出我们可以在产生信号前利用方法 signal(int signum, sighandler_t handler) 设置信号的处理。如果没有调用此方法,系统就会调用默认处理方法:中止程序,显示提示信息(就是我们经常遇到的问题)。我们可以调用系统的处理方法,也可以自定义处理方法。

对一个已经收到FIN包的socket调用read方法, 如果接收缓冲已空, 则返回0,
这就是常说的表示连接关闭. 但第一次对其调用write方法时, 如果发送缓冲没问题,
会返回正确写入(发送). 但发送的报文会导致对端发送RST报文,
因为对端的socket已经调用了close, 完全关闭, 既不发送, 也不接收数据. 所以,
第二次调用write方法(假设在收到RST之后), 会生成SIGPIPE信号, 导致进程退出.

为了避免进程退出, 可以捕获SIGPIPE信号, 或者忽略它,
给它设置SIG_IGN信号处理函数:

signal(SIGPIPE, SIG_IGN);

这样, 第二次调用write方法时, 会返回-1, 同时errno置为SIGPIPE.
程序便能知道对端已经关闭.

要通过TCP远程连接C代码,你需要使用Socket编程。下面是一个简单的例子: 1. 服务端代码 ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define PORT 8888 int main() { int server_fd, new_sock; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); // 创建TCP套接字 if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 设置套接字选项 if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { perror("setsockopt failed"); exit(EXIT_FAILURE); } // 绑定地址和端口 address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); if (bind(server_fd, (struct sockaddr *) &address, sizeof(address)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // 监听连接 if (listen(server_fd, 3) < 0) { perror("listen failed"); exit(EXIT_FAILURE); } printf("Waiting for connections...\n"); // 接受连接请求 if ((new_sock = accept(server_fd, (struct sockaddr *) &address, (socklen_t *) &addrlen)) < 0) { perror("accept failed"); exit(EXIT_FAILURE); } printf("Connection accepted from %s:%d\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port)); // 接收数据 char buffer[1024] = {0}; int valread; valread = read(new_sock, buffer, 1024); printf("Received message: %s\n", buffer); // 发送响应 char *response = "Hello from server!"; send(new_sock, response, strlen(response), 0); printf("Response sent\n"); return 0; } ``` 2. 客户端代码 ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define SERVER_IP "127.0.0.1" #define PORT 8888 int main() { int sock = 0; struct sockaddr_in serv_addr; char *message = "Hello from client!"; char buffer[1024] = {0}; // 创建TCP套接字 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("\n Socket creation error \n"); return -1; } memset(&serv_addr, '0', sizeof(serv_addr)); // 设置服务器地址和端口 serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); if (inet_pton(AF_INET, SERVER_IP, &serv_addr.sin_addr) <= 0) { printf("\nInvalid address/ Address not supported \n"); return -1; } // 连接服务器 if (connect(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { printf("\nConnection Failed \n"); return -1; } printf("Connected to server\n"); // 发送数据 send(sock, message, strlen(message), 0); printf("Message sent\n"); // 接收响应 int valread; valread = read(sock, buffer, 1024); printf("Received response: %s\n", buffer); return 0; } ``` 编译并分别运行服务端和客户端代码即可进行TCP远程连接。注意修改SERVER_IP为你实际的服务器IP地址。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值