Linux网络编程之聊天程序(TCP协议之select)

服务器端:server.c

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

#include <string.h>

#include <sys/types.h>

#include <netinet/in.h>

#include <sys/socket.h>

#include <sys/wait.h>

#include <unistd.h>

#include <arpa/inet.h>

#include <sys/time.h>

#include <sys/types.h>



#define MAXBUF 1024



int main(int argc, char **argv)

{

        int sockfd, new_fd;

        socklen_t len;

        struct sockaddr_in my_addr, their_addr;

        unsigned int myport, lisnum;

        char buf[MAXBUF + 1];

        fd_set rfds;

        struct timeval tv;

        int retval, maxfd = -1;



        if (argv[2])

                myport = atoi(argv[2]);       /* 将命令行字符串转换为整数。用于端口 */

        else

                myport = 8888;                           /* 设置默认端口 */

        if (argv[3])

                lisnum = atoi(argv[3]);                     /* 监听队列大小 */

        else

                lisnum = 2;

        if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {             /* 创建socket对象 */

                perror("socket");

                exit(EXIT_FAILURE);

        }



        bzero(&my_addr, sizeof(my_addr));

        my_addr.sin_family = PF_INET;                /* 地址协议 */

        my_addr.sin_port = htons(myport);             /* 地址端口 */

        if (argv[1])

            my_addr.sin_addr.s_addr = inet_addr(argv[1]);

        else

            my_addr.sin_addr.s_addr = INADDR_ANY;                    /* 否则默认本机随意地址 */

        if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) == -1) { /* 绑定地址信息 */

           perror("bind");

           exit(EXIT_FAILURE);

        }

         if (listen(sockfd, lisnum) == -1) { 
/* 监听网络 ,最大队列数是lisnum*/

            perror("listen");

            exit(EXIT_FAILURE);

         }



         while (1) 

{

            printf ("\n----wait for new connect\n");

                len = sizeof(struct sockaddr);

if ((new_fd =accept(sockfd, (struct sockaddr *) &their_addr,&len)) == -1) {

/* 堵塞等待连接。连接成功返回新的socket描写叙述符,their_addr存储client的sockaddr 地址信息

            perror("accept");

              exit(errno);

            } else

            printf("server: got connection from %s, port %d, socket %d\n", 

inet_ntoa(their_addr.sin_addr),ntohs(their_addr.sin_port), new_fd);

            while (1) 

{

              FD_ZERO(&rfds);    
/* 清零rfds集合 */

                FD_SET(0, &rfds);  
/* 把标准输入加入rfds集合 */

                FD_SET(new_fd, &rfds);                 /*
把new_fd加入rfds集合 */

                maxfd = new_fd;

                tv.tv_sec = 1;

                tv.tv_usec = 0;

                retval = select(maxfd + 1, &rfds, NULL, NULL, &tv);    /*
maxfd + 1监听的最大值加一 */

                if (retval == -1) 

{

perror("select");

exit(EXIT_FAILURE);

} else if (retval == 0) {

                  continue;

                } 

else

{

                    if (FD_ISSET(0, &rfds))                        /* 假设是标准输入可读 */

{

                          bzero(buf, MAXBUF + 1);

                        fgets(buf, MAXBUF, stdin);

                          if (!strncasecmp(buf, "quit", 4)) {

                            printf("i will quit!\n");

                              break;

                          }

                          len = send(new_fd, buf, strlen(buf) - 1, 0);

                        if (len > 0)

                                printf ("send successful,%d byte send!\n",len);

                          else {

                              printf("send failure!");

                            break;

                            }

}

                    if (FD_ISSET(new_fd, &rfds))             /* 假设是new_fd可读 */



                            bzero(buf, MAXBUF + 1);

                          len = recv(new_fd, buf, MAXBUF, 0);

                            if (len > 0)

                                printf ("recv success :'%s',%dbyte recv\n", buf, len);

                            else

{

                              if (len < 0)

                                printf("recv failure\n");

                                else

{

                                  printf("the ohter one end ,quit\n");

                                  break;

}

                            }

            }

                 }

}

            close(new_fd);

            printf("need othe connecdt (no->quit)");

            fflush(stdout);

            bzero(buf, MAXBUF + 1);

            fgets(buf, MAXBUF, stdin);

            if (!strncasecmp(buf, "no", 2)) 

{

                printf("quit!\n");

                break;

            }

        }

        close(sockfd);

        return 0;

}



客户端程序:client.c

#include <stdio.h>

#include <string.h>

#include <errno.h>

#include <sys/socket.h>

#include <resolv.h>

#include <stdlib.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <unistd.h>

#include <sys/time.h>

#include <sys/types.h>



#define MAXBUF 1024

int main(int argc, char **argv)

{

    int sockfd, len;

    struct sockaddr_in dest;

    char buffer[MAXBUF + 1];

    fd_set rfds;

    struct timeval tv;

    int retval, maxfd = -1;



    if (argc != 3) 

    {

        printf("argv format errno,pls:\n\t\t%s IP port\n",argv[0], argv[0]);

        exit(EXIT_FAILURE);

    }

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 

    {

        perror("Socket");

        exit(EXIT_FAILURE);

    }

    bzero(&dest, sizeof(dest));

    dest.sin_family = AF_INET;

    dest.sin_port = htons(atoi(argv[2]));

    if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) 

    {

        perror(argv[1]);

        exit(EXIT_FAILURE);

    }



    if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) 

    {

        perror("Connect ");

        exit(EXIT_FAILURE);

    }



    printf("\nget ready pls chat\n");

    while (1) 

{

        FD_ZERO(&rfds);

        FD_SET(0, &rfds);

        FD_SET(sockfd, &rfds);

        maxfd = sockfd;

        tv.tv_sec = 1;

        tv.tv_usec = 0;

        retval = select(maxfd + 1, &rfds, NULL, NULL, &tv);

        if (retval == -1) 

{

            printf("select %s", strerror(errno));

            break;

        } 

else if (retval == 0)

            continue;

else

{

            if (FD_ISSET(sockfd, &rfds)) 

{

                bzero(buffer, MAXBUF + 1);

                len = recv(sockfd, buffer, MAXBUF, 0);

                if (len > 0)

                    printf ("recv message:'%s',%d byte recv\n",buffer, len);

                else 

{

                    if (len < 0)

                        printf ("message recv failure\n");

                    else

{

                        printf("the othe quit ,quit\n");

                    break;

}

                }

            }

            if (FD_ISSET(0, &rfds)) 

{

                bzero(buffer, MAXBUF + 1);

                fgets(buffer, MAXBUF, stdin);

                if (!strncasecmp(buffer, "quit", 4)) {

                    printf("i will quit\n");

                    break;

                }

                len = send(sockfd, buffer, strlen(buffer) - 1, 0);

                if (len < 0) {

                    printf ("message send failure");

                    break;

                } else

                    printf

                        ("send success,%d byte send\n",len);

            }

        }

    }

    close(sockfd);

    return 0;

}

測试方法例如以下:

gcc server.c -o server

gcc client.c -o client

./server 172.16.148.114  8888       /* 一个终端下。172.16.148.114是我虚拟机的IP地址*/

./client 172.16.148.114  8888      /*另外 一个终端下 */



select函数不会使用的參考这篇文章:http://blog.csdn.net/qq_21792169/article/details/50450360

上一篇:在Android程序中使用Modbus协议时报 java.net.SocketException: recvfrom failed: ECONNRESET解决办法


下一篇:答题小程序开发之socket编程 微信小程序答题 直播答题开发 直播弹幕使用web socket编程