首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 操作系统 > UNIXLINUX >

linux socket服务器有关问题,求大神详细解释下程序运行过程,代码如下

2013-06-25 
linux socket服务器问题,求大神详细解释下程序运行过程,代码如下~在网上看了这个程序,服务器端可以接收多

linux socket服务器问题,求大神详细解释下程序运行过程,代码如下~
    在网上看了这个程序,服务器端可以接收多个客户端传来的信息,并且可以判断是否有新连接、连接数目、是否达到最大连接数等,小女子不才,函数的作用和代码差不多理解了,但就是想不了服务器是怎么运行的,流程是怎样的理不清思路,还希望各位大神们能抽空看一下这个程序,能详细解释下运行流程,最好再有相关代码的解释,十分感谢!!!!!

程序代码如下:
#include<stdio.h>

#include<stdlib.h>

#include<sys/socket.h>

#include<sys/types.h>

#include<unistd.h>

#include<string.h>

#include<netinet/in.h>

#include<netdb.h>

#include<arpa/inet.h>


#define PORT 1205

#define MAXNUM 3

#define MAXSIZE 1024


int fd[MAXNUM];//

int connect_num; 


void showclient()
{
    int i;
    printf("client amount: %d\n", connect_num);
    for (i = 0; i <MAXNUM; i++) {
        printf("[%d]:%d  ", i, fd [i]);
    }
    printf("\n\n");
}


int main()

{

struct sockaddr_in server;

struct sockaddr_in client;

bzero(&server,sizeof(server));

bzero(&client,sizeof(client));

char buf[MAXSIZE];


int sock_fd=socket(AF_INET,SOCK_STREAM,0);

if(sock_fd==-1)

{

print(“socket failed!\n”);

exit(-1);




server.sin_family=AF_INET;

server.sin_port=htons(PORT);

server.sin_addr=htons(“192.168.2.4”);


int bind_fd=bind(sock_fd, (struct sockaddr*)server,sizeof(server));

if(bind_fd==-1)

{

printf(“bind failed!\n”);

exit(-1);

}

int listen_fd=listen(sock_fd,MAXNUM);

if(listen_fd==-1)

{

printf(“listen failed!\n”);

exit(-1);

}

printf(“listen port:%d\n”,PORT);

}

fd_set fdsr;

    int maxsock;

    struct timeval tv;

    connect_num= 0;

    sin_size = sizeof(client_addr);

    maxsock = sock_fd;//??
    while (1) {
        // 初始化文件描述符集合
        FD_ZERO(&fdsr);
        FD_SET(sock_fd, &fdsr);

        // timeout setting
 tv.tv_sec = 30;
tv.tv_usec = 0;
        for (i = 0; i < MAXNUM; i++) {
            if (fd [i] != 0) {
                FD_SET(fd [i], &fdsr);
            }
        }

        ret = select(maxsock + 1, &fdsr, NULL, NULL, &tv);
        if (ret < 0) {
            perror("select");
            break;


        } //select失败

else if (ret == 0) {
            printf("timeout\n");
            continue;
        for (i = 0; i < connect_num; i++) {
            if (FD_ISSET(fd [i], &fdsr)) {
                ret = recv(fd [i], buf, sizeof(buf), 0);
                if (ret <= 0) {        // client close
                    printf("client[%d] close\n", i);
                    close(fd[i]);
                    FD_CLR(fd[i], &fdsr);
                    fd[i] = 0;
                } else {        // receive data
                    if (ret < MAXSIZE)
                        memset(&buf[ret], '\0', 1);
                    printf("client[%d] send:%s\n", i, buf);
                }
            }
        }
        if (FD_ISSET(sock_fd, &fdsr)) {
            new_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size);
            if (new_fd <= 0) {
                perror("accept");
                continue;
            }

            if (conn_amount <MAXNUM) {
                fd[connect_num++] = new_fd;
                printf("new connection client[%d] %s:%d\n", connect_num,
                        inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
                if (new_fd > maxsock)
                    maxsock = new_fd;


            }
            else {
                printf("max connections arrive, exit\n");
                send(new_fd, "bye", 4, 0);
                close(new_fd);
                break;
            }
        }
        showclient();
    }

    for (i = 0; i < MAXNUM; i++) {
        if (fd[i] != 0) {
            close(fd[i]);
        }
    }
    exit(0);
}

[解决办法]
大概看了下,就是把接收到的客户端连接(描述符)保存在fd_A中,用select监控多个套接口的状态,循环完成:
监控fd_A中套接字的可读状态;
有可读的客户端套接字时,读取信息;
有客户端连接时接收新的客户端连接;
客户端连接没有超过上限时,加入到fd_A中;

[解决办法]
ok,这个代码没问题了。前面应该是少复制了一个"}"。

fd_A[BACKLOG]数据里面保存所有已连接套接字,如果元素值为0,表示这个元素还未被使用,conn_amount记录了当前的连接总数。

while(1)前面的代码应该都能看懂吧!while(1)里面,select调用前,前面的所有代码都是为了调用select做的准备,即设置好fd_set。select后面,根据返回值ret,如果ret<0表示select调用出错了,所以直接break结束循环;如果返回0标识超时,continue接着下次循环;如果返回大于0,程序首先判断所有已连接套接字,是否有数据可读,有的话就读出来然后打印。这步做完之后,接着判断监听套接字(sockfd)是否可读,如果可读表示有新的连接到来,如果连接数没满就加到fd_A,如果满了就break(这里有问题,连接数一旦满了服务器进程就结束了)。

热点排行