0%

Linux Socket通信服务端自动关闭

Linux Socket通信时,客户端和服务端发送信息时,关闭客户端进程时,服务端会关闭这个socket连接的原因

在尝试使用Linux Socket通信时,客户端和服务端发送信息时,关闭客户端进程时,服务端会关闭这个socket连接的原因,代码如下:

服务端程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
while(true)
{
char buf[MAX_BUFFER];
char *return_msg = (char*)"got it";
memset(&buf, 0, sizeof(buf));
ssize_t read_bytes = read(client_socket, &buf, sizeof(buf));
if(read_bytes > 0)
{
printf("message from client fd %d: %s\n", client_socket, buf);
write(client_socket, return_msg, sizeof(return_msg));
}
else if(read_bytes == 0)
{
printf("client fd %d disconnect\n", client_socket);
close(client_socket);
break;
}
else
{
close(client_socket);
errif(true, "Socket failed to read");
}
}

客户端程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
while(true)
{
char buf[MAX_BUFFER];
memset(&buf, 0, sizeof(buf));
scanf("%s", buf);
ssize_t write_types = write(client_socket, &buf, sizeof(buf));
if(write_types == -1)
{
printf("socket already disconnected, can't write anymore!\n");
break;
}
memset(&buf, 0, sizeof(buf));
ssize_t read_bytes = read(client_socket, &buf, sizeof(buf));
if(read_bytes > 0)
{
printf("message from server: %s\n", buf);
}
else if(read_bytes == 0)
{
printf("server has disconnected");
break;
}
else
{
close(client_socket);
errif(true, "socket read error");
}
}

可以观察到,通信过程为客户端通过scanf函数发送信息,发送后收到服务端的回复。

遇到的问题/现象如下:当关闭客户端程序进程时,服务端程序自动输出client fd 4 disconnect

原因:强行关闭客户终端时,client进程交付给init进程,当init进程查询到client后将其杀掉,但是在杀掉之前,由于关掉了终端(主要是关掉了输入缓冲区),导致本来阻塞中的scanf返回EOF,程序得以继续执行发送操作。服务器发现client有消息传入,但是在尝试回应client的时候client被初始进程杀掉。然后就变成了给已经关闭的socket发送数据。这个时候服务端的read会返回0,表示EOF,接着调用read_bytes的分支,输出结果

注:不是因为scanf返回EOF,写入了write函数,导致服务端的read读到0

修改客户端代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
std::ofstream outfile("../temp/output.txt"); 
while(true)
{
char buf[MAX_BUFFER];
memset(&buf, 0, sizeof(buf));
char temp[MAX_BUFFER];
memset(&temp, 0, sizeof(temp));
scanf("%s", temp);
outfile << "exe continue" << std::endl;
strncpy(buf, "hello", MAX_BUFFER - 1);
ssize_t write_types = write(client_socket, &buf, sizeof(buf));
if(write_types == -1)
{
printf("socket already disconnected, can't write anymore!\n");
break;
}
memset(&buf, 0, sizeof(buf));
ssize_t read_bytes = read(client_socket, &buf, sizeof(buf));
if(read_bytes > 0)
{
printf("message from server: %s\n", buf);
}
else if(read_bytes == 0)
{
printf("server has disconnected");
break;
}
else
{
close(client_socket);
errif(true, "socket read error");
}
}
outfile.close();

此时写入的buf一直都是hello,强行关闭进程,强行关闭进程也会出现以上现象。而且文件输出结果不会包含停止进程的那次输出,说明不会执行到下一步。

注2:当输入数据大于MAX_BUFFER的大小时,会分多次发送。