unix网络编程-简易聊天室

原理很简单,也是参照的书上的代码,用select来实现的,其中重要的部分是服务器端,当检测到某一个端口FD_ISSET()的时候就要对所有在线的端口进行群发,以达到群体聊天的目的。

直接上代码

//这个是客户端文件
//myclient.c
#include "unp.h"

int main(int argc, char const *argv[]) {
  int listenfd;
  struct sockaddr_in servaddr;

  listenfd = socket(AF_INET, SOCK_STREAM, 0);

  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(SERV_PORT);
  inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

  connect(listenfd, (SA*)&servaddr, sizeof(servaddr));

  str_cli(stdin, listenfd);

  return 0;
}
//这个是服务器端文件
//myserver.c
#include "unp.h"
#include <stdlib.h>

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                buff[MAXLINE];
    socklen_t           clilen;
    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, (SA *) &servaddr, sizeof(servaddr));

    listen(listenfd, LISTENQ);

    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);
/* end fig01 */

/* include fig02 */
    for ( ; ; ) {
        rset = allset;      /* structure assignment */
        nready = select(maxfd+1, &rset, NULL, NULL, NULL);

        if (FD_ISSET(listenfd, &rset)) {    /* new client connection */
            clilen = sizeof(cliaddr);
            connfd = accept(listenfd, (SA *) &cliaddr, &clilen);
#ifdef  NOTDEF
            printf("new client: %s, port %d\n",
                    Inet_ntop(AF_INET, &cliaddr.sin_addr, 4, NULL),
                    ntohs(cliaddr.sin_port));
#endif

            for (i = 0; i < FD_SETSIZE; i++)
                if (client[i] < 0) {
                    client[i] = connfd; /* save descriptor */
                    break;
                }
            // if (i == FD_SETSIZE)
            //  err_quit("too many clients");

            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;
            memset(buf, 0, sizeof(buf));
            if (FD_ISSET(sockfd, &rset)) {
                if ( (n = read(sockfd, buf, MAXLINE)) == 0) {
                        /*4connection closed by client */
                    close(sockfd);
                    FD_CLR(sockfd, &allset);
                    client[i] = -1;
                } else

                    //判断有几个客户端 并进行转发
                    for(int j=0; j<=maxi; j++){
                        if(client[j] < 0)
                            continue;

                        sprintf(buff,"%d: ", sockfd);
                        strcat(buff, buf);
                        write(client[j], buff, strlen(buff));
                    }


                if (--nready <= 0)
                    break;              /* no more readable descriptors */
            }
        }
    }
}
/* end fig02 */
  • 运行方法

    //先对文件进行编译
    gcc myserver.c -o tcpserer
    gcc myclient.c mystrcli.c -o tcpclient
    
    //在客户端1上启动一个服务器,并放入后台
    ./tcpserver &
    //在客户端1上启动一个客户
    ./tcpclient 127.0.0.1
    //在客户端2上启动另一个客户
    ./tcpclient 127.0.0.1
    
    //至此,两个客户端就可以对话了
  • 运行截图

    客户端1
    这里写图片描述

    客户端2
    这里写图片描述

  • 完整程序可以从我的github上面下载,地址如下:

    https://github.com/xixihahag/-select-unix-

猜你喜欢

转载自blog.csdn.net/qq_24889575/article/details/81482445