服务器端: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

Linux网络编程之聊天程序(TCP协议之select)的更多相关文章

  1. 网络编程应用:基于TCP协议【实现一个聊天程序】

    要求: 基于TCP协议实现一个聊天程序,客户端发送一条数据,服务器端发送一条数据 客户端代码: package Homework1; import java.io.IOException; impor ...

  2. Linux网络编程——连接和面向连接的协议之间没有区别

    网络编程中最重要的概念就是连接取向(connection-oriented)和无连接(connectionless)协议.虽然本质.两者之间的区别是不难理解,编程的人来说,却是个非常easy混淆的问题 ...

  3. Java网络编程——UDP聊天程序

    UDP简介 UDP协议的全称是用户数据报,在网络中它与TCP协议一样用于处理数据报.在OSI模型中,UDP位于第四层--传输层,处于IP协议额上一层.UDP有不提供数据报分组.组装以及不能对数据报排序 ...

  4. UNIX/Linux网络编程基础:图解TCP/IP协议栈

    目录 1.主机到网络层协议:以太网协议 2.IP协议 3.网际控制报文协议(ICMP) 4.传输控制协议(TCP) 5.用户数据报文协议(UDP) 6.流控制传输协议(SCTP) 7.地址解析协议(A ...

  5. 网络编程(二)--TCP协议、基于tcp协议的套接字socket

    一.TCP协议(Transmission Control Protocol 传输控制协议) 1.可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会 ...

  6. python网络编程——使用UDP、TCP协议收发信息

    UDP UDP是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送. UDP传输数据时有大小限制,每个被传输的数据报必须限定在64KB之内. UDP ...

  7. 网络编程(二)——TCP协议、基于tcp协议的套接字socket

    TCP协议与基于tcp协议的套接字socket 一.TCP协议(流式协议) 1.可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会超过IP数据包的 ...

  8. 网络编程应用:基于TCP协议【实现对象传输】--练习

    要求: 基于TCP协议实现,客服端向服务器发送一个对象 服务器接受并显示用户信息 ,同时返回给客户端 "数据已收到" 建一个Student类,属性:name age Student ...

  9. 网络编程应用:基于TCP协议【实现文件上传】--练习

    要求: 基于TCP协议实现一个向服务器端上传文件的功能 客户端代码: package Homework2; import java.io.File; import java.io.FileInputS ...

随机推荐

  1. zimg 启动命令

    cd zimgcd bin ./zimg conf/zimg.lua

  2. Jenkins多选项框使用

    多选框的使用场景还是挺多的,比如发布多个服务,或者选择哪些服务器 想要使用多选项,则需要安装插件extend choice parameter,然后在项目中配置参数化构建过程 配置完上面,我们就可以在 ...

  3. WP SyntaxHighlighter 初探

    继上篇文章发布后,我随即去网上找了下博客园.CSDN他们用的高亮工具,果然都是用的别人的,SyntaxHighlighter.去官网上看了下,很强大,包含各种经典配色以及多语言.要想在wordpres ...

  4. Codeforces 1037 H. Security

    \(>Codeforces \space 1037\ H. Security<\) 题目大意 : 有一个串 \(S\) ,\(q\) 组询问,每一次给出一个询问串 \(T\) 和一个区间 ...

  5. 字符串的模板 Manacher kmp ac自动机 后缀数组 后缀自动机

    为何scanf("%s", str)不需要&运算 经常忘掉的字符串知识点,最好不加&,不加&最标准,指针如果像scanf里一样加&是错的,大概是未定 ...

  6. Android Studio --> Gradle Build设置自动

    ps:http://www.cnblogs.com/kangyi/p/4448398.html 应用场景 通常情况下我们的apps发布后也就是release模式下log是不显示的,debug模式下是显 ...

  7. Linux6.9用RPM方式安装MySQL5.7.21

    1.下载安装包 wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.21-1.el6.x86_64.rpm-bundle.tar ...

  8. linux开发node相关的工具

    epel-release yum install epel-release node yum install nodejs mongodb 安装mongodb服务器端 yum install mong ...

  9. MEF 导入(Import)和导出(Export)

    前言: MEF不同于其他IOC容器(如:Castle)很重要的原因在于它使用了特性化编程模型(涉及到两个概念:“特性”和“编程模型”). 特性(Attribute):举例来说就是我们在开发过程中在类上 ...

  10. FastStone Capture 8.4 注册码

    原文:https://blog.csdn.net/mlin_123/article/details/51557079 name:bluman serial/序列号/注册码:VPISCJULXUFGDD ...