Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1184949
  • 博文数量: 573
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 66
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-28 16:21
文章分类

全部博文(573)

文章存档

2018年(3)

2016年(48)

2015年(522)

分类: LINUX

2015-12-02 15:40:26


点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <sys/types.h>
  4. #include <sys/socket.h>
  5. #include <netinet/in.h>
  6. #include <arpa/inet.h>
  7. #include <sys/wait.h>
  8. #include <pthread.h>
  9. #include <stdlib.h>
  10. #include <time.h>
  11. #include <unistd.h>
  12. #include <sys/stat.h>
  13. #include <fcntl.h>
  14. #include <errno.h>
  15. #include <termios.h>
  16. #include <sys/time.h>
  17. #include <sys/timeb.h>
  18. #include <stdarg.h>
  19. #include <netdb.h>
  20. #include <poll.h>

  21. #define SER_IP "127.0.0.1" /*服务器的IP地址*/
  22. #define OPEN_MAX 512

  23. int read_socket(int socket_id, char *pbuf, int len);
  24. int write_socket(int socket_id, char *pbuf, int len);

  25. int main(int argc, char ** argv) /*服务端程序*/
  26. {    
  27.     char    serv_ip[20];
  28.     char    guest_ip[20];
  29.     memset(serv_ip, 0, sizeof(serv_ip));
  30.     memset(guest_ip, 0, sizeof(guest_ip));
  31.     
  32.     int count;
  33.     pid_t pid;
  34.     char ip_buf[32];
  35.     char readbuf[1024];
  36.     int sockfd = -1; /*监听套接字*/
  37.     int newfd = -1; /*连接套接字*/
  38.     int ret = -1;
  39.     int opt = 1;
  40.     int len;
  41.     int i=0;
  42.     int read_count = 1; /*读取次数*/
  43.     struct sockaddr_in seraddr; /*用来保存服务器自己的ip地址和端口号的*/
  44.     struct sockaddr_in cliaddr; /*用来保存连接过来的客户的ip地址和端口号的*/
  45.     struct sockaddr_in bindaddr; /*用来保存连接过来的客户的ip地址和端口号的*/
  46.     struct sockaddr lbindaddr;
  47.     
  48.     memset(ip_buf, 0, sizeof(ip_buf));
  49.     memset(readbuf, 0, sizeof(readbuf));
  50.     
  51.     memset(&seraddr, 0, sizeof(seraddr));
  52.     memset(&cliaddr, 0, sizeof(cliaddr));
  53.     memset(&bindaddr, 0, sizeof(bindaddr));
  54.     memset(&lbindaddr, 0, sizeof(lbindaddr));
  55.     
  56.     
  57.     printf("有数据可读:POLLIN=[%d]\n", POLLIN);
  58.     //printf("有普通数据可读:POLLRDNORM=[%d]\n", POLLRDNORM);
  59.     //printf("有优先数据可读:POLLRDBAND=[%d]\n", POLLRDBAND);
  60.     //printf("有紧迫数据可读:POLLPRI=[%d]\n", POLLPRI);
  61.     
  62.     //printf("写普通数据不会导致阻塞:POLLOUT=[%d]\n", POLLOUT);
  63.     //printf("写普通数据不会导致阻塞:POLLWRNORM=[%d]\n", POLLWRNORM);
  64.     //printf("写优先数据不会导致阻塞:POLLWRBAND=[%d]\n", POLLWRBAND);
  65.     
  66.     //printf("fd发生错误:POLLERR=[%d]\n", POLLERR);
  67.     //printf("fd挂起:POLLHUP=[%d]\n", POLLHUP);
  68.     //printf("fd非法:POLLNVAL=[%d]\n", POLLNVAL);

  69.     
  70.     sockfd = socket(AF_INET, SOCK_STREAM, 0); /*创建连接套接字,TCP协议*/
  71.     if(sockfd < 0)
  72.     {
  73.         return -1;
  74.     }
  75.     setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); /*将服务端设置具有端口号可以重复*/

  76.     seraddr.sin_family = AF_INET; /*指定服务器地址协议族*/
  77.     seraddr.sin_port = htons(4989);     /*指定要监听的服务器的端口号*/
  78.     /*seraddr.sin_addr.s_addr = INADDR_ANY;*/ /*指定要监听的服务器的ip:0.0.0.0:则客户端可连 127.0.0.1 和 真实的主机地址*/
  79.     
  80.     char * hostname = NULL;
  81.     hostname = getenv("HOST");
  82.     if(hostname == NULL)
  83.     {
  84.         printf("HOST环境变量不存在!\n");
  85.         exit(-1);
  86.     }
  87.     struct hostent * myhost;
  88.     myhost = gethostbyname(hostname);
  89.     if(myhost == NULL)
  90.     {
  91.         printf("myhost is null!\n");
  92.         exit(-1);
  93.     }
  94.     bcopy(myhost->h_addr, &seraddr.sin_addr, myhost->h_length);
  95.     char ipbuf[128];
  96.     memset(ipbuf, 0, sizeof(ipbuf));
  97.     inet_ntop(AF_INET, &seraddr.sin_addr.s_addr, ipbuf, sizeof(ipbuf));
  98.     printf("主机名=[%s],IP地址=[%s]\n", myhost->h_name, ipbuf);
  99.     printf("IP地址=[%s]\n", ipbuf);

  100.     ret = bind(sockfd, (struct sockaddr*)&seraddr, sizeof(struct sockaddr)); /*将IP地址,端口号和文件绑定,为套接字命名*/
  101.     if(ret < 0)
  102.     {
  103.         printf("bind err! ret = [%d]\n", ret);
  104.         return -1;
  105.     }
  106.     
  107.     ret = listen(sockfd, 10); /*listen一执行,sockfd就能接受连接请求*/
  108.     if(ret < 0)
  109.     {
  110.         return -1;
  111.     }
  112.     
  113.     //定义
  114.     struct pollfd fdset[OPEN_MAX];
  115.   for(i = 0; i < OPEN_MAX; i++)
  116.   {
  117.       fdset[i].fd = -1;//循环将fd赋值为-1.
  118.   }
  119.     
  120.     count = 0;
  121.     //将0和sockfd加入到pollfd结构体中
  122.     fdset[0].fd = 0;
  123.     fdset[0].events = POLLIN; //监视是否有数据可读
  124.     count++;
  125.     fdset[1].fd = sockfd;
  126.     printf("监听sockfd=[%d]\n", sockfd);
  127.     fdset[1].events = POLLIN;
  128.     //fdset[1].events = POLLOUT;
  129.     count++;
  130.     int j;

  131.     while(1)
  132.   {
  133.        /*
  134.        函数原型 : int poll(struct pollfd *fds, nfds_t nfds, int timeout);
  135.        功能 : 使用poll查询这 count 个描述符的状态。poll可以同时查询多个文件。
  136.                     有描述符准备好,则立即返回,没有描述符准备好,则等待timeout时间,还未准备好,再返回。
  137.        参数 :
  138.                    fds : 所有的文件的描述符到保存在集合fds中
  139.                    nfds : 查询的文件数目
  140.                    timeout : 超时时间,以ms为单位的
  141.                    
  142.        */
  143.           ret = poll(fdset, count, 1000);
  144.           for(i=0; i<count; i++)
  145.           {
  146.                   if(fdset[i].revents & POLLIN) //判断描述符fdset[i]的POLLIN是否触发
  147.                   {
  148.                           if(fdset[i].fd == 0) /*是标准输入设备*/
  149.                           {
  150.                                   printf("从标准输入设备读取\n");
  151.                                   memset(readbuf, 0, sizeof(readbuf));
  152.                                     ret = read(0, readbuf, sizeof(readbuf));
  153.                                     printf("read=[%s] ret = [%d]\n", readbuf, ret);
  154.                           }
  155.                           else if(fdset[i].fd == sockfd) /*监听套接字sockfd可读:表示sockfd已经接受客户端的连接请求*/
  156.                           {
  157.                                     printf("有客户端已经连接:可以用accept获得连接请求并建立连接!\n");
  158.                                     len = sizeof(cliaddr); /*-结果参数*/
  159.                                     /*if((newfd=accept(sockfd,(struct sockaddr *)&cliaddr,(socklen_t *)&len))==-1)*/
  160.                                     if((newfd=accept(sockfd, (struct sockaddr *)NULL, (socklen_t *)NULL)) == -1) /*不关心客户端标识*/
  161.                          {
  162.                          perror("accept() failed");
  163.                          exit(1);
  164.                          }
  165.                                  struct sockaddr_in serv;
  166.                                  struct sockaddr_in guest;
  167.                                  socklen_t serv_len = sizeof(serv);
  168.                                  socklen_t guest_len = sizeof(guest);
  169.                                 
  170.                                  getsockname(newfd, (struct sockaddr *)&serv, &guest_len);
  171.                                  getpeername(newfd, (struct sockaddr *)&guest, &serv_len);
  172.                                 
  173.                                  inet_ntop(AF_INET, &guest.sin_addr.s_addr, guest_ip, sizeof(guest_ip));
  174.                                  inet_ntop(AF_INET, &serv.sin_addr.s_addr, serv_ip, sizeof(serv_ip));
  175.                                  printf("服务端IP和PORT[%s]:[%d]\n", serv_ip, ntohs(serv.sin_port));
  176.                                  printf("客户端IP和PORT[%s]:[%d]\n", guest_ip, ntohs(guest.sin_port));
  177.                         
  178.                          fdset[count].fd = newfd; /*将连接套接字加入pollfd结构中*/
  179.                          printf("count=[%d]\n", count);
  180.                          printf("fdset[count].fd newfd=[%d]\n", newfd);
  181.                                     fdset[count].events = POLLIN;
  182.                                     count++;
  183.                           }
  184.                           else /*走到这里的,都是连接套接字*/
  185.                           {
  186.                                   printf("count=[%d]\n", count);
  187.                                   printf("服务器读取套接字[%d]的内容:\n", fdset[i].fd);
  188.                                     memset(readbuf, 0, sizeof(readbuf));
  189.                                     ret = read(fdset[i].fd, readbuf, sizeof(readbuf));
  190.                                     printf("read=[%s] ret = [%d]\n", readbuf, ret);
  191.                                     for(j=0; j<ret; j++)
  192.                                     {
  193.                                             printf("***[%02x]***\n", readbuf[j]);
  194.                                     }
  195.                                     
  196.                                     printf("服务器写入套接字[%d]的内容:\n", fdset[i].fd);
  197.                                     ret = write(fdset[i].fd, readbuf, strlen(readbuf));
  198.                                     printf("write=[%s] ret = [%d]\n", readbuf, ret);
  199.                           }
  200.                   }
  201.       }
  202.   }
  203.   close(sockfd);

  204.     return 0;
  205. }

阅读(386) | 评论(0) | 转发(0) |
0

上一篇:getnetent函数

下一篇:getprotoent函数

给主人留下些什么吧!~~