服务器端: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. 【Python初级】由判定回文数想到的,关于深浅复制,以及字符串反转的问题

    尝试用Python实现可以说是一个很经典的问题,判断回文数. 让我们再来看看回文数是怎么定义的: 回数是指从左向右读和从右向左读都是一样的数,例如1,121,909,666等 解决这个问题的思路,可以 ...

  2. Xamarin 2017.9.19更新

     Xamarin 2017.9.19更新   本次更新是添加Xamarin.iOS对iOS 11和Xcode 9的支持.Visual Studio 2017升级到15.3.5获得更新功能.Visual ...

  3. 某DP题目5

    题意 一个游戏里有k种装备,一开始等级为1,每打败一个怪兽,会随机掉落一件一种类型的装备,它的等级为[1,t+1]中的随机一个数,t为当前佩戴的类型的装备的等级,若掉落t+1等级的装备,就会佩戴该装备 ...

  4. 四、python之 if while for

    一.if条件判断 if 条件判断: 逻辑操作…… …… else: 逻辑操作…… 其中"判断条件"成立时(非零),则执行后面的语句,而执行内容可以多行,以缩进来区分表示同一范围. ...

  5. BZOJ 4517: [Sdoi2016]排列计数 错排公式

    4517: [Sdoi2016]排列计数 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4517 Description 求有多少种长度为 ...

  6. bzoj 2428: [HAOI2006]均分数据 随机化

    2428: [HAOI2006]均分数据 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/ ...

  7. MySQL之char、varchar和text的设计

    最近有表结构设计中出现了varchar(10000)的设计引起了大家的讨论,我们下面就来分析分析. 首先我们先普及一下常识: 1.char(n)和varchar(n)中括号中n代表字符的个数,并不代表 ...

  8. jQuery Mobile 页面事件

    jQuery Mobile 页面事件 在 jQuery Mobile 中与页面打交道的事件被分为四类: Page Initialization - 在页面创建前,当页面创建时,以及在页面初始化之后 P ...

  9. printf回到上一行开头以及回到本行开头的方法

    回到上一行开头 #include <stdio.h> #include <unistd.h> int main(void) { ; ){ printf("%d\n&q ...

  10. sourceinsight 工程和源码不在同一个盘符下

    建立sourceinsight的时候,si工程可以和项目源码不在同一个盘下面,即si工程在D盘下,而阅读的源码在E盘下. 方法步骤如下: 下看一下目录结构: Y:\work\Hi3521\Hi3521 ...