0

基本的にデータを受信するために別のスレッドを生成するマルチスレッドTCPクライアントを以下に記述しましたが、データは標準入力でユーザーからの入力のみを取得してメインスレッドに書き込まれています。

ここで、ctrl ^ Dを押すと、実装がループから出て(getline()呼び出しの周り)、ソケット記述子を閉じますが、ネットワーク上にFINは表示されません。ただし、close()をshutdown()に置き換えると違いが生じます。close()を使用すると、FINはワイヤに送信されませんが、shutdown(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);
        }
    }
}
4

2 に答える 2

-1

shutdown(WR) を呼び出すと FIN が送信されますが、close にはほとんど違いがありません。fd 参照カウントが等しくない場合、0 は FIN を送信しません。

于 2013-01-12T14:49:28.053 に答える
-1

close(socket) の前に shutdown( socket, SHUT_WR) を使用できます

于 2015-07-27T15:15:51.913 に答える