0

我正在使用 Lwip 协议编写 TCP 服务器,通常服务器可以连接到多个 TCP 客户端。但是我有一个问题,服务器不能连接三个以上的活动连接。第 4 个或更多客户端因未知原因无法连接。我查看了论坛并尝试增加MEMP_NUM_TCP_PCBopt.h (lwip-x86_64\include\lwip\opt.h) 的数量限制,但没有帮助。

以下是我的代码,我的问题是使用 LWIP 是否有最大连接限制?最大连接数为 3 个或更多?

//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;
}
4

1 回答 1

0

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

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

    MEMP_NUM_TCP_PCB 100
    MEMP_NUM_TCP_PCB_LISTEN 100
    MEMP_NUM_NETCONN 100

现在服务器可以突破连接限制,可以建立3个以上的活动TCP连接。

于 2015-08-30T07:09:02.020 回答