C Socket网络编程细节问题

accept

accept()的函数原型如下:

int accept(int socket, struct sockaddr *restrict address,
           socklen_t *restrict address_len);

需要注意的是第三个参数address_len,在Linux manual中是这么描述的:

Either a null pointer, if address is a null pointer, or a pointer to a socklen_t object which on input specifies the length of the supplied sockaddr structure, and on output specifies the length of the stored address.

也就是说在调用前后存储的内容是不同的,有各自的作用,在调用之前就需要设置为第二个参数address的大小。

一个正确的accpet应该使用以下的形式:

struct sockaddr_in client_address;
socklen_t client_address_size = sizeof(client_address);
connection_fd = accept(socket_fd, (struct sockaddr *) &client_address, &client_address_size);

通信边界

对于一个echo服务,要通过传递数据大小来约定对方下一次read的数据量。一个正确的回显程序的client应当如下:

int len = (int) strnlen(message, BUFFER_SIZE) + 1;
write(connection_fd, &len, sizeof(int));
write(connection_fd, message, len);

read(connection_fd, &len, sizeof(len));
read(connection_fd, message, len);
printf("[echo_rep] %s\n", message);

通常来讲对于文本都是通过strnlen来计算长度,但是需要+1以包含最后的\0,否则程序运行之后,很有可能会出现因为\0缺失而把buffer中后面的字符一起打印出来的情况,因为C中不遇到\0printf()是不会停下来的(卡其脱离太)。

但在read的时候,一定要保证直接按给的数量读取。总之要理解好这一个通信规则。

SIGPIPE

SIGPIPE这一个信号在编写网络应用的时候一定要注意,不对这一个信号量进行处理会导致服务程序的崩溃。

在Linux下使用kill命令模拟程序收到SIGPIPE信号。

kill -PIPE <PID>
pkill --signal=SIGPIPE <Programme Name>

Last updated

Was this helpful?