我已经写下面这基本上产生一个单独的线程,用于接收然而,数据被写入在主线程的数据多线程TCP客户端的接近()'发送只在标准输入上接受了来自用户的输入。TCP FIN不做一个多线程TCP客户端
现在,在按下CTRL^d再执行出来的循环(围绕函数getline()调用),并关闭套接字描述符,但没有FIN看到在电线上。但是,使用shutdown()替换close()会有所作为。关闭()关闭时FIN没有发送,但关闭(fd,SHUT_WR)FIN是在线上发送的?
为什么这种差异?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
void *receiver (void *arg);
pthread_t thrid;
int sockfd;
int reUse = 0;
int
main (int argc, char *argv[])
{
struct sockaddr_in servaddr;
struct sockaddr_in clntaddr;
char *line;
size_t len = 0;
size_t read;
int bytes;
if (argc < 6)
{
printf
("Usage:%s <Server Ipv4 address> <Server Port> <SO_REUSEADDR Yes(1)/No(0))> <Close(0)/SHUT_RD(1)/SHUT_WR(2)/SHUT_RDWR(3)> <sleep (in sec)> [Client IPv4 address] [Client Port]\n",
argv[0]);
return -1;
}
/*
* AF_INET, AF_INET6, AF_UNIX, AF_NETLINK
* SOCK_STREAM (TCP), SOCK_DGRAM (UDP), SOCK_RAW
*/
if ((sockfd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{
printf ("Failed to create socket: %s\n", strerror (errno));
return -1;
}
/*
* set SO_REUSEADDR option for the UDP server socket
*/
reUse = atoi (argv[3]);
if (reUse)
{
int i = 1;
setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &i,
sizeof (i));
}
bzero (&clntaddr, sizeof (struct sockaddr_in));
if (argc == 8)
{
printf ("doing bind......\n");
clntaddr.sin_family = AF_INET;
clntaddr.sin_port = htons (atoi (argv[7]));
inet_aton (argv[6], &clntaddr.sin_addr);
if (bind
(sockfd, (struct sockaddr *) &clntaddr,
sizeof (struct sockaddr_in)) == -1)
{
perror ("Failed to bind");
close (sockfd);
return -1;
}
}
bzero (&servaddr, sizeof (struct sockaddr_in));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons (atoi (argv[2]));
inet_aton (argv[1], &servaddr.sin_addr);
if (-1 ==
connect (sockfd, (struct sockaddr *) &servaddr,
sizeof (struct sockaddr_in)))
{
printf ("Failed to connect: %s\n", strerror (errno));
return -1;
}
if (pthread_create (&thrid, NULL, receiver, NULL) < 0)
{
printf ("Failed to create thread\n");
}
while ((read = getline (&line, &len, stdin)) != -1)
{
bytes = send (sockfd, line, len, 0);
if (bytes < 0)
{
if (errno == EINTR)
continue;
else
printf ("%Read error %s\n", pthread_self(),
strerror (errno));
}
}
if (0 == atoi (argv[4]))
{
printf ("doing close()....\n");
close (sockfd);
}
else if (1 == atoi (argv[4]))
{
printf ("doing shutdown(..., SHUTRD)....\n");
shutdown (sockfd, SHUT_RD);
}
else if (2 == atoi (argv[4]))
{
printf ("doing shutdown(..., SHUTWR)....\n");
shutdown (sockfd, SHUT_WR);
}
else if (3 == atoi (argv[4]))
{
printf ("doing shutdown(..., SHUTRDWR)....\n");
shutdown (sockfd, SHUT_RDWR);
}
if (line)
free (line);
sleep (atoi (argv[5]));
}
void *
receiver (void *arg)
{
char buff[512];
int bytes;
while (1)
{
bytes = recv (sockfd, buff, sizeof (buff), 0);
if (bytes < 0)
{
if (errno == EINTR)
continue;
else
printf ("%Read error %s\n", pthread_self(),
strerror (errno));
pthread_exit (-1);
}
else if (bytes == 0)
{
printf ("connection closed by Peer\n");
close(sockfd);
pthread_exit (-1);
}
else
{
printf ("Msg Received:%s\n", buff);
}
}
}
你的意思,因为插座是的recv()系统调用中使用一个单独的线程,因此其参考正在增加? –
@VivekGupta这是不可预测的,因为有一个竞争条件。对'close'的调用可能在调用'recv'之前,之中或之后发生。 –