【问题标题】:connect: Cannot assign requested address in linux连接:无法在linux中分配请求的地址
【发布时间】:2018-01-16 06:23:45
【问题描述】:

我有 2 个程序。基本上我正在尝试查看 TCP (SYN, FIN)。

server.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


/*
 * error - wrapper for perror
 */
void error(char *msg) {
    perror(msg);
    exit(1);
}

int main(int argc, char **argv) {
    int parentfd; /* parent socket */
    int childfd; /* child socket */
    int portno; /* port to listen on */
    int clientlen; /* byte size of client's address */
    struct sockaddr_in serveraddr; /* server's addr */
    struct sockaddr_in clientaddr; /* client addr */
    struct hostent *hostp; /* client host info */
    char buf[BUFSIZE]; /* message buffer */
    char *hostaddrp; /* dotted decimal host addr string */
    int optval; /* flag value for setsockopt */
    int n; /* message byte size */
    static int cnt;

    /*
     * check command line arguments
     */
    if (argc != 2) {
        fprintf(stderr, "usage: %s <port>\n", argv[0]);
        exit(1);
    }
    portno = atoi(argv[1]);

    /*
     * socket: create the parent socket
     */
    parentfd = socket(AF_INET, SOCK_STREAM, 0);
    if (parentfd < 0)
        error("ERROR opening socket");

    /* setsockopt: Handy debugging trick that lets
     * us rerun the server immediately after we kill it;
     * otherwise we have to wait about 20 secs.
     * Eliminates "ERROR on binding: Address already in use" error.
     */
    optval = 1;
    setsockopt(parentfd, SOL_SOCKET, SO_REUSEADDR,
            (const void *)&optval , sizeof(int));

    /*
     * build the server's Internet address
     */
    bzero((char *) &serveraddr, sizeof(serveraddr));

    /* this is an Internet address */
    serveraddr.sin_family = AF_INET;

    /* let the system figure out our IP address */
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);

    /* this is the port we will listen on */
    serveraddr.sin_port = htons((unsigned short)portno);

    /*
     * bind: associate the parent socket with a port
     */
    if (bind(parentfd, (struct sockaddr *) &serveraddr,
                sizeof(serveraddr)) < 0)
        error("ERROR on binding");

    /*
     * listen: make this socket ready to accept connection requests
     */
    if (listen(parentfd, 5) < 0) /* allow 5 requests to queue up */
        error("ERROR on listen");

    /*
     * main loop: wait for a connection request, echo input line,
     * then close connection.
     */
    clientlen = sizeof(clientaddr);
    while (1) {

        /*
         * accept: wait for a connection request
         */
        childfd = accept(parentfd, (struct sockaddr *) &clientaddr, &clientlen);
        if (childfd < 0)
            error("ERROR on accept");

        printf("%d: Connected \n", ++cnt);
        close(childfd);
    }
}

================================================ ====================================

Client.c

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>

void tcpConnectComplete(int fd)
{
    uint32_t             index       = 0;
    int                  max_fd, res, optval;
    socklen_t            optlen;
    struct               timeval timeout;
    int                  timeoutCount = 0;
    fd_set               wr_fd;
    while(1)
    {
        max_fd = res = 0;
        optval = -1;
        timeout.tv_sec  = 0;
        timeout.tv_usec = ((5 * 1000) / 3 );

        FD_ZERO(&wr_fd);
        FD_SET(fd, &wr_fd);

        res = select(fd+1, NULL, &wr_fd, NULL, &timeout);

        if(res == 0 || (res < 0 && errno == EINTR))
        {
            if(++timeoutCount == 3)
            {
                break;
            }
            continue;
        }
        else if(res < 0)
        {
            break;
        }

        if(0 == FD_ISSET(fd, &wr_fd))
        {
            continue;
        }

        optval = -1;
        optlen = (socklen_t)sizeof(optval);
        if(-1 == getsockopt(fd, SOL_SOCKET, SO_ERROR, &optval, &optlen))
        {
            printf("TCP Connect failed\n");
            return;
        }
        else
        {
            if(0 == optval)
            {
                printf("TCP Connect success\n");
            }
            else
            {
                printf("TCP Connect failed: optval=%d\n", optval);
            }
            return;
        }
    }
}

void tcpConnect(void)
{
    struct sockaddr_in  addr;
    int                 sockFd = 0;
    int                 enable = 1;
    int                 flags;

    /* Created a socket */
    if(-1 == (sockFd = socket(AF_INET, SOCK_STREAM, 0)))
    {
        perror("setsockopt");
        return;
    }

    if(setsockopt(sockFd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
    {
        perror("setsockopt");
        return;
    }
    /* Set non block mode */
    flags = fcntl(sockFd, F_GETFL, NULL);
    if (-1 == fcntl(sockFd, F_SETFL, flags | O_NONBLOCK))
    {
        perror("fcntl");
        return;
    }

    /* Bind to source ip and port */
    memset(&addr, 0, sizeof(addr));
    addr.sin_family      = AF_INET;
    addr.sin_port        = htons(39589);
    addr.sin_addr.s_addr = inet_addr("192.168.56.101");
    //addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    if(-1 == bind(sockFd, (struct sockaddr*)&addr, sizeof(addr)))
    {
        perror("bind");
        return;
    }


    /* TCP Connect */
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(39591);
    addr.sin_addr.s_addr = inet_addr("192.168.56.102");
    //addr.sin_addr.s_addr = inet_addr("127.0.0.1");

    if(-1 == connect(sockFd, (struct sockaddr*) &addr, sizeof(addr)))
    {
        perror("connect");
        if (errno == EINPROGRESS)
            tcpConnectComplete(sockFd);
    }
    else
    {
        printf("Connect success\n");
    }
    close(sockFd);
    close(0);
}

int main(void)
{
    int i;

    for (i = 0; i < 10; i++)  {
        tcpConnect();
    };

    return 0;
}

如果同时运行服务器和客户端程序,我会看到以下输出(没有粘贴服务器输出,因为那里没有奇怪的东西):

./client 
connect: Operation now in progress
TCP Connect success
connect: Cannot assign requested address
connect: Operation now in progress
TCP Connect success
connect: Cannot assign requested address
connect: Cannot assign requested address
connect: Operation now in progress
TCP Connect success
connect: Cannot assign requested address
connect: Cannot assign requested address
connect: Cannot assign requested address
connect: Cannot assign requested address

我的问题是为什么会出现“无法分配请求的地址”的连接失败?程序有什么问题? 请帮助理解这一点。

【问题讨论】:

  • 你能告诉你为什么将客户端绑定到特定地址吗?为什么不能只创建一个套接字并连接到服务器。
  • 我希望客户端始终使用相同的 (ip+port)。
  • 好吧,在这种情况下,您必须在使用之前关闭该地址。并等到地址空闲
  • 服务器机器的ip地址是什么?
  • 为什么在 client.c 中使用 bind ?确保在下次提问时在您的问题中发布必要的信息。这次更新问题的详细信息。

标签: linux system-calls connect


【解决方案1】:

你能试试下面的东西吗? 我没有给你直接的答案,而是给你调试任何 tcp 客户端服务器程序的工具。试一试。以便将来您可以自己解决它们。

  1. 尝试检查netstat -tan 输出。定期监控它。将给出 tcp 会话是否中断的想法。
  2. 然后尝试检查wireshark 日志。数据包的流动方式。
  3. 最后你可以在linux中尝试netcat包来测试服务器和客户端了解更多见man nc

【讨论】:

    猜你喜欢
    • 2021-05-19
    • 1970-01-01
    • 2014-11-19
    • 2023-01-18
    • 1970-01-01
    • 2021-11-03
    • 2013-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多