作者:2009级嵌入式  刘志卿


这是一个局域网通信程序,客户端通过连接服务器向局域网中的其它主机进行通讯.
 服务器程序,用下面的命令直接编译,运行.

[root@localhost liu]# gcc server.c -o server 

-------------------------------------------------------------------------------------*/ 

                            /*server.c*/ 

#include 
 
 
#include 
  
  
#include 
   
   
#include 
    
    
#include "wrap.h" 
    

#define MAXLINE 80 
    
#define SERV_PORT 8000 
    

int main(int argc, char **argv) 
    
{ 
    
    int i, maxi, maxfd, listenfd, connfd, sockfd; 
    
    int nready, client[FD_SETSIZE]; 
    
    ssize_t n; 
    
    fd_set rset, allset; 
    
    char buf[MAXLINE]; 
    
    char str[INET_ADDRSTRLEN]; 
    
    socklen_t cliaddr_len; 
    
    struct sockaddr_in cliaddr, servaddr; 
    

    listenfd = Socket(AF_INET, SOCK_STREAM, 0); 
    

    bzero(&servaddr, sizeof(servaddr)); 
    
    servaddr.sin_family = AF_INET; 
    
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
    
    servaddr.sin_port = htons(SERV_PORT); 
    

    Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); 
    

    Listen(listenfd, 20); 
    

    maxfd = listenfd;    /* initialize */ 
    
    maxi = -1;        /* index into client[] array */ 
    
    for (i = 0; i < FD_SETSIZE; i++) 
    
        client[i] = -1;    /* -1 indicates available entry */ 
    
    FD_ZERO(&allset); 
    
    FD_SET(listenfd, &allset); 
    

    for (;;) { 
    
        rset = allset;    /* structure assignment */ 
    
        nready = select(maxfd + 1, &rset, NULL, NULL, NULL); 
    
        if (nready < 0) 
    
            perr_exit("select error"); 
    

        if (FD_ISSET(listenfd, &rset)) {    /* new client connection */ 
    
            cliaddr_len = sizeof(cliaddr); 
    
            connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); 
    

            printf("received from %s at PORT %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port)); 
    

            for (i = 0; i < FD_SETSIZE; i++) 
    
                if (client[i] < 0) { 
    
                    client[i] = connfd;    /* save descriptor */ 
    
                    break; 
    
                } 
    
            if (i == FD_SETSIZE) { 
    
                fputs("too many clients\n", stderr); 
    
                exit(1); 
    
            } 
    

            FD_SET(connfd, &allset);    /* add new descriptor to set */ 
    
            if (connfd > maxfd) 
    
                maxfd = connfd;    /* for select */ 
    
            if (i > maxi) 
    
                maxi = i;    /* max index in client[] array */ 
    

            if (--nready == 0) 
    
                continue;    /* no more readable descriptors */ 
    
        } 
    

        for (i = 0; i <= maxi; i++) {    /* check all clients for data */ 
    
            if ((sockfd = client[i]) < 0) 
    
                continue; 
    
            if (FD_ISSET(sockfd, &rset)) { 
    
                if ((n = Read(sockfd, buf, MAXLINE)) < 0) {    //读取客户端发送的内容 
    
                    /*connection closed by client */ 
    
                    Close(sockfd);                               //如果读取失败则关闭连接 
    
                    FD_CLR(sockfd, &allset);                   //把这个文件描述符从连接中清除 
    
                    client[i] = -1;                            //把客户端标志设为-1 
    
                } else { 
    

                    int j; 
    
                    for (j = 0; j <= maxi; j++) { 
    
                        if (FD_ISSET(sockfd, &rset)) 
    
                            Write(client[j], buf, n);            //把已读到的数据发送给每一个连接的客户端 
    

                    } 
    

                } 
    

                if (--nready == 0) 
    
                    break;    /* no more readable descriptors */ 
    
            } 
    
        } 
    
    } 
    
}


/*------------------------------------------------------------------------------------
执行过程如下:

[root@localhost liu]# ./server 
    
received from 127.0.0.1 at PORT 33679                   //客户端连接上服务器 
    
received from 127.0.0.1 at PORT 33680 
    
-------------------------------------------------------------------------------------*/


注释:程序编译后直接运行,为了可以看到结果,可以打开多个终端进行测试,也可以在局域网内,两台以上的电脑进行测试.如果是局域网内多台电脑测试,则需要服务器端打开8000

端口.用下面的命令编译程序.

[root@localhost liu]# gcc client.c -o client 
    
--------------------------------------------------------------------------------------------*/ 
    

                            /* client.c */ 
    
#include 
     
     
#include 
      
      
#include 
       
       
#include 
        
        
#include "wrap.h" 
        
#include 
         
         
#include 
          
          
#include 
           
           

#define MAXLINE 80 
           
#define SERV_PORT 8000 
           

int main(int argc, char *argv[]) 
           
{ 
           
    struct sockaddr_in servaddr; 
           
    char buf[MAXLINE]; 
           
    int sockfd, n; 
           
    pid_t pid; 
           

    sockfd = Socket(AF_INET, SOCK_STREAM, 0); 
           

    bzero(&servaddr, sizeof(servaddr)); 
           
    servaddr.sin_family = AF_INET; 
           
    inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr); 
           
    servaddr.sin_port = htons(SERV_PORT); 
           

    Connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); 
           

    pid = fork();                                       //分支为两个进程 
           

    if (pid > 0) {        //父进程 
           
        while (fgets(buf, MAXLINE, stdin) != NULL) { 
           
            Write(sockfd, buf, strlen(buf));              //向客户端发送数据 
           
        } 
           
    } 
           
    if (pid == 0) {        //子进程 
           
        int b_on = 1; 
           
        ioctl(sockfd, FIONBIO, &b_on); 
           
        for (;;) 
           
            if ((n = Read(sockfd, buf, MAXLINE)) > 0)     //向服务器接收数据 
           
                Write(STDOUT_FILENO, buf, n);              //把读到的数据写进标准输出 
           
    } 
           
    Close(sockfd); 
           
    return 0; 
           
}



执行过程如下:

[root@localhost liu]# ./client 
           
ni hao a                                            //客户端向服务器发送数据 
           
ni hao a                                            //服务器端接收数据后发送给每一个已连接的客户端 
           
hello 
           
hello 
           
hello! 
           
hello!