简体   繁体   English

Recv-Q +发送-Q>写入字节

[英]Recv-Q+Send-Q>write bytes

I write a tcp server and a tcp client,the client only send data to server and print how many bytes it writed,the server only accept the connection,and then I use netstat to show the socket's Recv-Q and Send-Q,and I found that Recv-Q+send-Q > write bytes. 我编写了一个TCP服务器和一个TCP客户端,客户端仅向服务器发送数据并打印写入的字节数,服务器仅接受连接,然后使用netstat显示套接字的Recv-Q和Send-Q,我发现Recv-Q + send-Q>写字节。 How does it happend? 它是怎么发生的?

client code:
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <stdarg.h>
#include <errno.h>

void error(int status, int err, const char *fmt, ...)
{
    va_list args;

    va_start(args, fmt);

    vfprintf(stderr, fmt, args);

    va_end(args);

    if (err != 0)
    {
        fprintf(stderr, "errno = %d, errmsg = %s\n", err, strerror(err));
    }

    if (status != 0)
    {
        exit(err);
    }
}

int set_address(const char *host, const char *serv, const char *protocol, sockaddr_in *addr)
{
    struct hostent *host_info;
    struct servent *serv_info;

    memset(addr, 0, sizeof(sockaddr_in));

    addr->sin_family = AF_INET;

    if (host != NULL)
    {
        if (inet_aton(host, &addr->sin_addr) != 0)
        {
            host_info = gethostbyname(host);

            if (host_info == NULL)
            {
                error(1, h_errno, "set_address failed, gethostbyname(%s) failed, errno = %d, errmsg = %s\n", host, h_errno, hstrerror(h_errno));
            }
            else
            {
                inet_aton(host_info->h_addr_list[0], &addr->sin_addr);
            }
        }
    }
    else
    {
        addr->sin_addr.s_addr = INADDR_ANY;
    }

    if (serv != NULL)
    {
        char * end_pos;

        addr->sin_port = htons(strtol(serv, &end_pos, 10));

        if (*end_pos != '\0')
        {
            serv_info = getservbyname(serv, protocol);

            if (serv_info == NULL)
            {
                error(1, h_errno, "set_address failed, getservbyname(%s, %s) faield\n", serv, protocol);
            }
            else
            {
                addr->sin_port = serv_info->s_port;
            }
        }
    }
}

int tcp_client(const char *host, const char *serv)
{
    struct sockaddr_in server;
    int fd;
    const int on = 1;

    set_address(host, serv, "tcp", &server);

    fd = socket(AF_INET, SOCK_STREAM, 0);

    if (fd < 0)
    {
        error(1, errno, "create socket failed\n");
    }

    if (connect(fd, (struct sockaddr *)&server, sizeof(server)) != 0)
    {
        error(1, errno, "connect to server failed\n");
    }

    return fd;
}

int main (int argc, char **argv)
{
    if (argc != 3)
    {
        printf("usage: %s <host> <port>\n", basename(argv[0]));
        exit(1);
    }

    char buf[1024];
    int fd;
    int total_write_bytes = 0, cur_write_bytes = 0;

    fd = tcp_client(argv[1], argv[2]);

    while (true)
    {
        cur_write_bytes = write(fd, buf, sizeof(buf));
        if (cur_write_bytes <= 0)
        {
            break;
        }
        total_write_bytes += cur_write_bytes;
        printf("total_write_bytes = %d, curr_write_bytes = %d\n", total_write_bytes, cur_write_bytes);
    }

    return 0;
}

server code:
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <stdarg.h>
#include <errno.h>

void error(int status, int err, const char *fmt, ...)
{
    va_list args;

    va_start(args, fmt);

    vfprintf(stderr, fmt, args);

    va_end(args);

    if (err != 0)
    {
        fprintf(stderr, "errno = %d, errmsg = %s\n", err, strerror(err));
    }

    if (status != 0)
    {
        exit(err);
    }
}

int set_address(const char *host, const char *serv, const char *protocol, sockaddr_in *addr)
{
    struct hostent *host_info;
    struct servent *serv_info;

    memset(addr, 0, sizeof(sockaddr_in));

    addr->sin_family = AF_INET;

    if (host != NULL)
    {
        if (inet_aton(host, &addr->sin_addr) != 0)
        {
            host_info = gethostbyname(host);

            if (host_info == NULL)
            {
                error(1, h_errno, "set_address failed, gethostbyname(%s) failed, errno = %d, errmsg = %s\n", host, h_errno, hstrerror(h_errno));
            }
            else
            {
                inet_aton(host_info->h_addr_list[0], &addr->sin_addr);
            }
        }
    }
    else
    {
        addr->sin_addr.s_addr = INADDR_ANY;
    }

    if (serv != NULL)
    {
        char * end_pos;

        addr->sin_port = htons(strtol(serv, &end_pos, 10));

        if (*end_pos != '\0')
        {
            serv_info = getservbyname(serv, protocol);

            if (serv_info == NULL)
            {
                error(1, h_errno, "set_address failed, getservbyname(%s, %s) faield\n", serv, protocol);
            }
            else
            {
                addr->sin_port = serv_info->s_port;
            }
        }
    }
}

int tcp_server(const char *host, const char *serv)
{
    struct sockaddr_in local;
    int fd;
    const int on = 1;

    set_address(host, serv, "tcp", &local);

    fd = socket(AF_INET, SOCK_STREAM, 0);

    if (fd < 0)
    {
        error(1, errno, "create socket failed");
    }

    if (bind(fd, (sockaddr *)&local, sizeof(local)) != 0)
    {
        error(1, errno, "bind to port %s:%s failed\n", host, serv);
    }

    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0)
    {
        error(1, errno, "set SO_REUSEADDR failed\n");
    }

    if (listen(fd, 100) != 0)
    {
        error(1, errno, "listen on %s:%s failed\n", host, serv);
    }

    return fd;
}

int main (int argc, char **argv)
{
    if (argc != 3)
    {
        printf("usage: %s <host> <port>\n", basename(argv[0]));
        exit(1);
    }

    int listen_fd, fd;
    struct sockaddr_in addr;
    socklen_t len;

    listen_fd = tcp_server(argv[1], argv[2]);

    fd = accept(listen_fd, (struct sockaddr *)&addr, &len);

    if (fd < 0)
    {
        error(1, errno, "accept an connection failed\n");
    }

    while (true)
    {
        sleep(5);
    }

    return 0;
}

this is the resulte: 结果是:

standard output result: standard output 标准输出结果: 标准输出

netstat result: netstat result netstat结果: netstat结果

tcpdump result: tcpdump结果:

14:17:16.633105 IP localhost.54393 > localhost.personal-agent: S 4282375064:4282375064(0) win 32767 14:17:16.633106 IP localhost.personal-agent > localhost.54393: S 4268411460:4268411460(0) ack 4282375065 win 32767 14:17:16.633115 IP localhost.54393 > localhost.personal-agent: . 14:17:16.633105 IP localhost.54393> localhost.personal-agent:S 4282375064:4282375064(0)赢得32767 14:17:16.633106 IP localhost.personal-agent> localhost.54393:S 4268411460:4268411460(0)ack 4282375065赢32767 14:17:16.633115 IP localhost.54393> localhost.personal-agent:。 ack 1 win 8192 14:17:16.633127 IP localhost.54393 > localhost.personal-agent: P 1:1025(1024) ack 1 win 8192 14:17:16.633130 IP localhost.personal-agent > localhost.54393: . ack 1 win 8192 14:17:16.633127 IP localhost.54393> localhost.personal-agent:P 1:1025(1024)ack 1 win 8192 14:17:16.633130 IP localhost.personal-agent> localhost.54393:。 ack 1025 win 8704 14:17:16.633156 IP localhost.54393 > localhost.personal-agent: P 1025:2049(1024) ack 1 win 8192 14:17:16.633159 IP localhost.personal-agent > localhost.54393: . ack 1025 win 8704 14:17:16.633156 IP localhost.54393> localhost.personal-agent:P 1025:2049(1024)ack 1 win 8192 14:17:16.633159 IP localhost.personal-agent> localhost.54393:。 ack 2049 win 8704 14:17:16.633167 IP localhost.54393 > localhost.personal-agent: P 2049:3073(1024) ack 1 win 8192 14:17:16.633169 IP localhost.personal-agent > localhost.54393: . ack 2049 win 8704 14:17:16.633167 IP localhost.54393> localhost.personal-agent:P 2049:3073(1024)ack 1 win 8192 14:17:16.633169 IP localhost.personal-agent> localhost.54393:。 ack 3073 win 8704 14:17:16.633176 IP localhost.54393 > localhost.personal-agent: P 3073:4097(1024) ack 1 win 8192 14:17:16.633179 IP localhost.personal-agent > localhost.54393: . ack 3073 win 8704 14:17:16.633176 IP localhost.54393> localhost.personal-agent:P 3073:4097(1024)ack 1 win 8192 14:17:16.633179 IP localhost.personal-agent> localhost.54393:。 ack 4097 win 8704 14:17:16.633185 IP localhost.54393 > localhost.personal-agent: P 4097:5121(1024) ack 1 win 8192 14:17:16.633188 IP localhost.personal-agent > localhost.54393: . ack 4097 win 8704 14:17:16.633185 IP localhost.54393> localhost.personal-agent:P 4097:5121(1024)ack 1 win 8192 14:17:16.633188 IP localhost.personal-agent> localhost.54393:。 ack 5121 win 8704 14:17:16.633195 IP localhost.54393 > localhost.personal-agent: P 5121:6145(1024) ack 1 win 8192 14:17:16.633198 IP localhost.personal-agent > localhost.54393: . ack 5121 win 8704 14:17:16.633195 IP localhost.54393> localhost.personal-agent:P 5121:6145(1024)ack 1 win 8192 14:17:16.633198 IP localhost.personal-agent> localhost.54393:。 ack 6145 win 8704 14:17:16.633204 IP localhost.54393 > localhost.personal-agent: P 6145:7169(1024) ack 1 win 8192 14:17:16.633206 IP localhost.personal-agent > localhost.54393: . ack 6145 win 8704 14:17:16.633204 IP localhost.54393> localhost.personal-agent:P 6145:7169(1024)ack 1 win 8192 14:17:16.633206 IP localhost.personal-agent> localhost.54393:。 ack 7169 win 8704 14:17:16.633213 IP localhost.54393 > localhost.personal-agent: P 7169:8193(1024) ack 1 win 8192 14:17:16.633215 IP localhost.personal-agent > localhost.54393: . ack 7169 win 8704 14:17:16.633213 IP localhost.54393> localhost.personal-agent:P 7169:8193(1024)ack 1 win 8192 14:17:16.633215 IP localhost.personal-agent> localhost.54393:。 ack 8193 win 8704 14:17:16.633222 IP localhost.54393 > localhost.personal-agent: P 8193:9217(1024) ack 1 win 8192 14:17:16.633224 IP localhost.personal-agent > localhost.54393: . ack 8193 win 8704 14:17:16.633222 IP localhost.54393> localhost.personal-agent:P 8193:9217(1024)ack 1 win 8192 14:17:16.633224 IP localhost.personal-agent> localhost.54393:。 ack 9217 win 8704 14:17:16.633230 IP localhost.54393 > localhost.personal-agent: P 9217:10241(1024) ack 1 win 8192 14:17:16.633233 IP localhost.personal-agent > localhost.54393: . ack 9217 win 8704 14:17:16.633230 IP localhost.54393> localhost.personal-agent:P 9217:10241(1024)ack 1 win 8192 14:17:16.633233 IP localhost.personal-agent> localhost.54393:。 ack 10241 win 8704 14:17:16.633239 IP localhost.54393 > localhost.personal-agent: P 10241:11265(1024) ack 1 win 8192 14:17:16.633242 IP localhost.personal-agent > localhost.54393: . ack 10241 win 8704 14:17:16.633239 IP localhost.54393> localhost.personal-agent:P 10241:11265(1024)ack 1 win 8192 14:17:16.633242 IP localhost.personal-agent> localhost.54393:。 ack 11265 win 8448 14:17:16.633249 IP localhost.54393 > localhost.personal-agent: P 11265:12289(1024) ack 1 win 8192 14:17:16.633251 IP localhost.personal-agent > localhost.54393: . ack 11265 win 8448 14:17:16.633249 IP localhost.54393> localhost.personal-agent:P 11265:12289(1024)ack 1 win 8192 14:17:16.633251 IP localhost.personal-agent> localhost.54393:。 ack 12289 win 8192 14:17:16.633258 IP localhost.54393 > localhost.personal-agent: P 12289:13313(1024) ack 1 win 8192 14:17:16.633261 IP localhost.personal-agent > localhost.54393: . ack 12289 win 8192 14:17:16.633258 IP localhost.54393> localhost.personal-agent:P 12289:13313(1024)ack 1 win 8192 14:17:16.633261 IP localhost.personal-agent> localhost.54393:。 ack 13313 win 7936 14:17:16.633269 IP localhost.personal-agent > localhost.54393: . ack 13313 win 7936 14:17:16.633269 IP localhost.personal-agent> localhost.54393:。 ack 14337 win 7680 14:17:16.671777 IP localhost.personal-agent > localhost.54393: . ack 14337 win 7680 14:17:16.671777 IP localhost.personal-agent> localhost.54393 :。 ack 31757 win 3325 14:17:16.879921 IP localhost.54393 > localhost.personal-agent: P 31757:45057(13300) ack 1 win 8192 14:17:16.959771 IP localhost.personal-agent > localhost.54393: . ack 31757 win 3325 14:17:16.879921 IP localhost.54393> localhost.personal-agent:P 31757:45057(13300)ack 1 win 8192 14:17:16.959771 IP localhost.personal-agent> localhost.54393:。 ack 45057 win 0 14:17:17.175771 IP localhost.54393 > localhost.personal-agent: . ack 45057 win 0 14:17:17.175771 IP localhost.54393> localhost.personal-agent :。 ack 1 win 8192 14:17:17.175786 IP localhost.personal-agent > localhost.54393: . ack 1 win 8192 14:17:17.175786 IP localhost.personal-agent> localhost.54393:。 ack 45057 win 0 14:17:17.607770 IP localhost.54393 > localhost.personal-agent: . ack 45057 win 0 14:17:17.607770 IP localhost.54393> localhost.personal-agent :。 ack 1 win 8192 14:17:17.607782 IP localhost.personal-agent > localhost.54393: . ack 1 win 8192 14:17:17.607782 IP localhost.personal-agent> localhost.54393:。 ack 45057 win 0 14:17:18.471768 IP localhost.54393 > localhost.personal-agent: . ack 45057 win 0 14:17:18.471768 IP localhost.54393> localhost.personal-agent :。 ack 1 win 8192 14:17:18.471775 IP localhost.personal-agent > localhost.54393: . ack 1 win 8192 14:17:18.471775 IP localhost.personal-agent> localhost.54393:。 ack 45057 win 0 ack 45057胜利0

Bytes that have been received but for which the acknowledge has not been received by the sender are in both the send queue and the receive queue. 发送队列和接收队列中都已收到但发送方尚未收到确认的字节。 They remain in the send queue because until they are acknowledged, the sender must be ready to re-send them. 它们保留在发送队列中,因为在被确认之前,发送者必须准备好重新发送它们。 They remain in the receive queue until the application calls a receive function and takes them out of the queue. 它们将保留在接收队列中,直到应用程序调用接收函数并将其从队列中取出为止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM