在Mini-OS中无法获得3个以上的活动TCP连接?

时间:2015-08-23 13:53:13

标签: sockets tcp xen lwip

我在 Mini-OS (xen中的操作系统)中编写TCP服务器,它可以连接到多个TCP客户端。我编写了一个处理多个TCP客户端的简单代码,但代码存在问题。问题是我无法让服务器连接三个以上的活动连接。第四个或更多客户端由于未知原因无法连接。我查看了论坛,并尝试在MEMP_NUM_TCP_PCB stubdom \ lwip-x86_64 \ include \ lwip \ opt.h )中增加opt.h的数量限制,并且它没有&#39 ; t帮助。

我在 Ubuntu 上运行TCP客户端。基于我所看到的,第四个客户端看起来似乎已连接,但在"write" function: "Resolver Error 0 (no error)"期间抛出异常

我该如何解决这个问题?

//server code 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define MYPORT 1234    // the port users will be connecting to
#define BACKLOG 2// how many pending connections queue will hold
#define BUF_SIZE 1024
int fd_A[BACKLOG];    // accepted connection fd
int conn_amount;      // current connection amount
void showclient()
{
    int i;
    printf("-----> client amount: %d\n", conn_amount);
    for (i = 0; i < BACKLOG; i++) {
        printf("BACKLOG%d ---> fd = %d\n", i, fd_A[i]);
    }
    printf("\n\n");
}
int main(void)
{
    sleep(1);
    printf("start server\n");
    int sock_fd, new_fd;             // listen on sock_fd, new connection on new_fd
    struct sockaddr_in server_addr;  // server address information
    struct sockaddr_in client_addr;  // connector's address information
    socklen_t sin_size;
    int yes = 1;
    char buf[BUF_SIZE];
    int ret;
    int i;
    if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }
    //if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
    /*if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
        //perror("setsockopt");
        //exit(1);
    }
    if (fcntl(sock_fd, F_SETFL, O_NONBLOCK) == -1) {
    printf("Set server socket nonblock failed\n");
    exit(1);
    }*/
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;         // host byte order
    server_addr.sin_port = htons(MYPORT);     // short, network byte order
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // automatically fill with my IP
    //memset(server_addr.sin_zero, '0', sizeof(server_addr.sin_zero));
    if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("bind");
        exit(1);
    }
    printf("listen...\n");
    if (listen(sock_fd, BACKLOG) == -1) {
        perror("listen");
        exit(1);
    }
    printf("listen port %d\n", MYPORT);
    fd_set fdsr, wfds, efds;
    int maxsock;
    struct timeval tv;
    conn_amount = 0;
    sin_size = sizeof(client_addr);
    maxsock = sock_fd;
    while (1) 
    {
    sleep(1);  // it's necessary
        // initialize file descriptor set
        FD_ZERO(&fdsr);
    FD_ZERO(&wfds);
        //FD_ZERO(&efds);
        FD_SET(sock_fd, &fdsr);  // add fd
        FD_SET(sock_fd, &wfds);  // add fd
        //FD_SET(sock_fd, &efds);  // add fd
        // timeout setting
        tv.tv_sec = 30;
        tv.tv_usec = 0;
        // add active connection to fd set
        for (i = 0; i < BACKLOG; i++) {
            if (fd_A[i] != 0) {
                FD_SET(fd_A[i], &fdsr);
            }
        }
    //printf("before select!!!!!!!!!!!! ret = %d\n", ret);
    if ((select(maxsock + 1, &fdsr, &wfds, (fd_set*) 0, (struct timeval*) 0)) < 0) {
            perror("select");
            break;
        } 

        // check every fd in the set
        for (i = 0; i < conn_amount; i++) 
        {
            if (FD_ISSET(fd_A[i], &fdsr)) // check which fd is ready
            {
                ret = recv(fd_A[i], buf, sizeof(buf), 0);
                if (ret <= 0) 
                {        // client close
                    printf("ret : %d and client[%d] close\n", ret, i);
                    close(fd_A[i]);
                    FD_CLR(fd_A[i], &fdsr);  // delete fd 
                    fd_A[i] = 0;
                    conn_amount--;
                }
                else 
                {        // receive data
                    if (ret < BUF_SIZE)
                        memset(&buf[ret], '\0', 1); // add NULL('/0')
                    printf("client[%d] send:%s\n", i, buf);
                }
            }
        }
    // check whether a new connection comes
        if (FD_ISSET(sock_fd, &fdsr))  // accept new connection 
        {
            new_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size);
            if (new_fd <= 0) 
            {
                perror("accept");
                continue;
            }
            // add to fd queue
            if (conn_amount < BACKLOG) 
            {
                fd_A[conn_amount++] = new_fd;
                printf("------> new connection client[%d] %s:%d\n", conn_amount,
                        inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
                if (new_fd > maxsock)  // update the maxsock fd for select function
                    maxsock = new_fd;
            }
            else 
            {
                printf("max connections arrive, exit\n");
                send(new_fd, "bye", 4, 0);
                close(new_fd);
                break;   
            }
        }
        //showclient();
    }
    // close other connections
    for (i = 0; i < BACKLOG; i++) 
    {
        if (fd_A[i] != 0) 
        {
            close(fd_A[i]);
        }
    }
    exit(0);
}

//client code
#include   <sys/stat.h>   
#include   <sys/types.h>   
#include   <sys/socket.h>   
#include   <stdio.h>   
#include   <malloc.h>   
#include   <netdb.h>   
#include   <fcntl.h>
#include   <unistd.h>
#include   <netinet/in.h>
#include   <arpa/inet.h>
#include   <string.h>
#define    RES_LENGTH  10240 
int     connect_socket(char * server,int serverPort);
int     send_msg(int sockfd,char * sendBuff);
char *  recv_msg(int sockfd);
int     close_socket(int sockfd);
int main(int argc, char ** argv)
{
    int   sockfd[1024] = {0};
    char  sendMsg[30]="zhangchengfei\r\n\r";
    char* res;
    int   port = 1234;
    char  ip[128] = {0};
    strncpy(ip, "10.107.19.62", 128);
    if(argc > 2)
    {
        strncpy(ip, argv[1], 128);
        port = atoi(argv[2]);
        printf("Input IP: %s, port : %d\n", ip, port);
    }
    else if(argc > 1)
    {   
        //port = atoi(argv[1]);
        //printf("Input port : %d\n", port);
    //
    int num_client = atoi(argv[1]);
    int i = 0;
    for (i = 0; i <= num_client; i++) {
        printf("start connect %d\n", i + 1);           
        sockfd[i]=connect_socket(ip, port);
        printf("connect %d OK\n", i + 1);   
        getchar();
    }
    for (i = 0; i <= num_client; i++) {
        send_msg(sockfd[i], sendMsg);
        /* res=recv_msg(sockfd); */

        printf("client %d send msg = %s\n", i + 1, sendMsg);
        //printf(res);
        //free(res);
        getchar();
    }
    for (i = 0; i <= num_client; i++) {
        close_socket(sockfd[i]);
        printf("close socket %d\n", i + 1);
        }
    }
    return 0;
}

int    connect_socket(char * server,int serverPort){
    int    sockfd=0;
    struct    sockaddr_in    addr;
    struct    hostent        * phost;

    if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0){
        herror("Init socket error!");
        return -1;
    }
    bzero(&addr,sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(serverPort);
    addr.sin_addr.s_addr = inet_addr(server);

    if(addr.sin_addr.s_addr == INADDR_NONE){
        phost = (struct hostent*)gethostbyname(server);
        if(phost==NULL){
            herror("Init socket s_addr error!");
            return -1;
        }
        addr.sin_addr.s_addr =((struct in_addr*)phost->h_addr)->s_addr;
    }
    if(connect(sockfd,(struct sockaddr*)&addr, sizeof(addr))<0)
    {
        perror("Connect server fail!");
        return -1; 
    }
    else
        return sockfd;
}


int send_msg(int sockfd,char * sendBuff)
{
    int sendSize=0;
    if((sendSize=send(sockfd,sendBuff,strlen(sendBuff),0))<=0){
        herror("Send msg error!");
        return -1;
    }else
        return sendSize;
}


char* recv_msg(int sockfd){
    char * response;
    int  flag=0,recLenth=0;
    response=(char *)malloc(RES_LENGTH);
    memset(response,0,RES_LENGTH);

    for(flag=0;;)
    {
        printf("======recv data:\n");
        if(( recLenth=recv(sockfd,response+flag,RES_LENGTH-flag,0))==-1 )
        {
            free(response);
            printf("Return value : %d\n", recLenth);
            perror("Recv msg error : ");
            return NULL;
        }
        else if(recLenth==0)
            break;
        else
        {
            printf("%d char recieved data : %s.\n", recLenth, response+flag);
            flag+=recLenth;
            recLenth=0;
        }
    }
    printf("Return value : %d\n", recLenth);
    response[flag]='0';
    return response;
}


int close_socket(int sockfd)
{
    close(sockfd);
    return 0;
}

1 个答案:

答案 0 :(得分:0)

我已解决Makefile./stubdom错误导致的问题,执行make crossclean后,我发现.o文件夹中仍存在lwip-x86_64个文件。所以我在Makefile中添加一个命令find . -name "*.o" | xargs rm -f,然后一切正常。

原因是lwip configure是由宏定义给出的,宏定义已经在预编译阶段被替换,所以如果我修改lwip configure并且没有删除.o文件,那么就没有了影响。以下是我在opt.h中修改的宏定义。

    MEMP_NUM_TCP_PCB 100
    MEMP_NUM_TCP_PCB_LISTEN 100
    MEMP_NUM_NETCONN 100

现在服务器可以突破连接限制并且可以建立3个以上的活动TCP连接,但遗憾的是我们遇到了另一个问题,服务器端只能接收61个连接请求的客户端。如果超过客户端编号,将报告服务器端错误,如下所示:

    ASSERTION FAILED: mbox->reader != mbox->writer at lwip-arch.c:124.
    Do_exit called!
    base is 0x29fe78 caller is 0x4d49d
    base is 0x29fe98 caller is 0x5a05a
    base is 0x29fec8 caller is 0x5a153
    base is 0x29fef8 caller is 0x634a1
    base is 0x29ff28 caller is 0x65074
    base is 0x29ff78 caller is 0x5d0dd
    base is 0x29ffc8 caller is 0x59822
    base is 0x29ffe8 caller is 0x33da

如何解决上述问题?