10.5 分隔TCP的I/O 程序
2025/12/16大约 3 分钟
10.5 分隔TCP的I/O 程序
前面的客户端读写按顺序进行,必须要在写完所有数据之后才能读,必须要在读完之后进行写入。
现在可以通过创建子进程将读、写过程分开。
分离I/O的好处:
- 逻辑清晰,更容易实现
- “提高频繁交换数据的程序性能”
分离I/O 和 不分离I/O数据交换的比较:
不分离
分离
客户端可以连续不断地发送数据,而不必等待收到回声
bug?奇奇怪怪,ob上有箭头,网页上没有。。。
参考
实现:
int main()
{
//...
if(connect(sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)
error_handling("connect() error!");
pid=fork();
if(pid==0)
write_routine(sock, buf);
else
read_routine(sock, buf);
close(sock);
return 0;
}
void read_routine(int sock, char *buf)
{
while(1)
{
int str_len=read(sock, buf, BUF_SIZE);
if(str_len==0)
return;
buf[str_len]=0;
printf("Message from server: %s", buf);
}
}
void write_routine(int sock, char *buf)
{
while(1)
{
fgets(buf, BUF_SIZE, stdin);
if(!strcmp(buf,"q\n") || !strcmp(buf,"Q\n"))
{
shutdown(sock, SHUT_WR);
return;
}
write(sock, buf, strlen(buf));
}
}效果:
ming@ubuntu:/media/sf_share/Network/build$ ./Network 192.168.56.1 10086
123
q
Message from server: 456Message from server: 789在输入q之后打印所有接收到的信息。。。
问:为什么服务端给客户端发送消息,第一次没有打印 “Message。。。”,第二次发送后才出现打印
ming@ubuntu:/media/sf_share/Network/build$ ./Network 192.168.56.1 10086
Debug: str_len=3增加了str_len的打印,这里可以看到确实有read到数据,那么应该会打印接收到的数据啊???
第二次发送:
ming@ubuntu:/media/sf_share/Network/build$ ./Network 192.168.56.1 10086
Debug: str_len=3
Message from server: 123Debug: str_len=2打印了第一次接收到的数据,以及第二次接收数据的长度
我的实现
实现:
pid_t pid = fork();
if(pid == -1)
unix_error("fork() error");
else if(pid == 0) { // child process: send to server
while(1) {
fgets(message, BUF_SIZE, stdin);
if(!strcmp(message,"q\n") || !strcmp(message,"Q\n")) {
break;
}
write(sock, message, strlen(message));
}
close(sock);
return 0;
}
else { // parent process: receive from server
while(1) {
str_len = read(sock, message, BUF_SIZE-1);
if(str_len == -1)
error_handling("read() error");
printf("str_len=%d\n", str_len);
if(str_len == 0)
break;
message[str_len] = 0;
printf("Message from server: %s \n", message);
}
}
close(sock);| 行号 | 功能 | 说明 |
|---|---|---|
| 4-14 | 子进程进行写入 | 从标准输入中读取要写入的数据,输入q或Q时退出 |
| 15-26 | 父进程读取 | 子进程退出的时候还是会产生中断,导致read 返回-1 |
效果:
connected
str_len=3
Message from server: 123
q
Child process 2414 terminated.
read() error Interrupted system call
str_len=-1
Message from server: 123子进程退出后无法发送消息给服务端(无法写入),但是仍能接收服务端消息。
shutdown
参考中子进程退出时通过shutdown关闭socket
如果把我的程序中的close(sock) 修改为shutdown(sock, SHUT_WR) 那么效果为:
connected
str_len=2
Message from server: 45
q
Child process 2665 terminated.
read() error Interrupted system call
str_len=-1
Message from server: 45
str_len=0输入q之后,子进程退出,首先进行信号处理,read再次读取时返回值为0.父进程也跟着退出。
在父进程 close(sock) 前进行sleep,查看文件状态:
Network 2705 ming 3u sock 0,9 0t0 26928 protocol: TCPsocket已经断开连接了,无法收发数据。
问:对于客户端socket,使用shutdown 会完全关闭 socket?而不是只关闭文件描述符?
注
父子进程读写的不是同一个buf 或者说是读写各自拥有的buf