Chinaunix首页 | 论坛 | 博客
  • 博客访问: 267479
  • 博文数量: 113
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1044
  • 用 户 组: 普通用户
  • 注册时间: 2015-02-15 16:09
文章分类

全部博文(113)

文章存档

2016年(5)

2015年(108)

我的朋友

分类: LINUX

2015-03-25 17:15:57

功能:实现多客户端连接的回射服务器,防止出现粘包。
server.c

点击(此处)折叠或打开

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <stdio.h>
  4. #include <netinet/in.h>
  5. #include <arpa/inet.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8. #include <stdlib.h>
  9. #include <fcntl.h>
  10. #include <sys/shm.h>
  11. #include<errno.h>

  12. #define MYPORT 8887
  13. #define QUEUE 20
  14. #define BUFFER_SIZE 1024
  15. struct packet
  16. {
  17.     int len;
  18.     char buf[BUFFER_SIZE];
  19. };
  20. ssize_t readn(int fd,void*buf,size_t count) ///用readn函数,防止在广域网上发生粘包
  21. {
  22.     size_t nleft = count;
  23.     ssize_t nread;
  24.     char *bufp =(char*)buf;
  25.     while(nleft>0)
  26.     {
  27.         if((nread =read(fd,bufp,nleft))<0)
  28.         {
  29.             if(errno ==EINTR)
  30.                 continue;
  31.             return -1;
  32.         }
  33.         else if(nread ==0)
  34.             return count - nleft;
  35.             
  36.         bufp +=nread;
  37.         nleft -=nread;
  38.         
  39.     }
  40.     return count;
  41. }
  42. ssize_t writen(int fd,const void*buf,size_t count) ///用writen函数,防止在广域网上发生粘包
  43. {
  44.     size_t nleft=count;
  45.     ssize_t nwritten;
  46.     char *bufp=(char*)buf;
  47.     while(nleft>0)
  48.     {
  49.         if((nwritten =write(fd,bufp,nleft))<0)
  50.         {
  51.             if(errno ==EINTR)
  52.                 continue;
  53.             return -1;
  54.         }
  55.         else if(nwritten ==0)
  56.             continue;
  57.             
  58.         bufp +=nwritten;
  59.         nleft -=nwritten;
  60.         
  61.     }
  62.     return count;
  63. }
  64. void do_service(int conn)
  65. {
  66.     
  67.     struct packet recvbuf;    
  68.     int n;
  69.     while(1)
  70.     {
  71.         memset(&recvbuf,0,sizeof(recvbuf));
  72.         int ret = readn(conn, &recvbuf.len, 4);
  73.         if (ret ==-1)
  74.         {
  75.         perror("read");
  76.         exit(1);
  77.         }
  78.         else if(ret <4)
  79.         {
  80.             printf("client close\n");
  81.         
  82.             break;
  83.         }
  84.         n=ntohl(recvbuf.len);
  85.         ret =readn(conn,recvbuf.buf,n);
  86.         if (ret ==-1)
  87.         {
  88.         perror("read");
  89.         exit(1);
  90.         }
  91.         else if(ret <n)
  92.         {
  93.             printf("client close\n");
  94.         
  95.             break;
  96.         }
  97.         
  98.         fputs(recvbuf.buf, stdout);
  99.         writen(conn, &recvbuf, 4+n);
  100.     }
  101. }
  102. int main()
  103. {
  104.         
  105.     
  106.     ///定义sockfd
  107.     int server_sockfd = socket(AF_INET,SOCK_STREAM, 0);

  108.     ///定义sockaddr_in
  109.     struct sockaddr_in server_sockaddr;
  110.     server_sockaddr.sin_family = AF_INET;
  111.     server_sockaddr.sin_port = htons(MYPORT);
  112.     server_sockaddr.sin_addr.s_addr = inet_addr("127.0.0.2");

  113.     ///bind,成功返回0,出错返回-1
  114.     int on =1; ///获得IP地址和端口
  115.     if(setsockopt(server_sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))==-1)   ///实现IP地址的重复利用,防止出现address used
  116.     {
  117.          perror("setsockopt");
  118.          exit(1);
  119.     }
  120.     printf("ip=%s port=%d\n",inet_ntoa(server_sockaddr.sin_addr),ntohs(server_sockaddr.sin_port));
  121.     if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1)
  122.     {
  123.         perror("bind");
  124.         exit(1);
  125.     }

  126.     ///listen,成功返回0,出错返回-1
  127.     int listenfd=listen(server_sockfd,QUEUE) ;
  128.     if(listenfd<0)
  129.     {
  130.         perror("listen");
  131.         exit(1);
  132.     }

  133.     ///客户端套接字
  134.    
  135.     struct sockaddr_in client_addr;
  136.     socklen_t length = sizeof(client_addr);

  137.     ///成功返回非负描述字,出错返回-1
  138.    
  139.     int conn ;
  140.     pid_t pid; ///fork 多个进程
  141.     while(1) ///多个客户端连接
  142.     {     if((conn = accept(server_sockfd, (struct sockaddr*)&client_addr, &length))<0)
  143.      {
  144.           perror("accept");
  145.           exit(1);
  146.          }
  147.           pid =fork();
  148.          if(pid==-1)
  149.      {
  150.             perror("fork");
  151.             exit(1);
  152.            }
  153.          if(pid==0)    ///子进程
  154.          {
  155.              close(server_sockfd);
  156.              do_service(conn);
  157.              exit(1);
  158.          }
  159.          else  ///父进程

  160.              close(conn);
  161.     
  162.     }
  163.     
  164.     return 0;
  165. }

client.c:

点击(此处)折叠或打开

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <stdio.h>
  4. #include <netinet/in.h>
  5. #include <arpa/inet.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8. #include <stdlib.h>
  9. #include <fcntl.h>
  10. #include <sys/shm.h>
  11. #include<errno.h>

  12. #define MYPORT 8887
  13. #define QUEUE 20
  14. #define BUFFER_SIZE 1024
  15. struct packet
  16. {
  17.     int len;
  18.     char buf[BUFFER_SIZE];
  19. };
  20. ssize_t readn(int fd,void*buf,size_t count) ///用readn函数,防止在广域网上发生粘包
  21. {
  22.     size_t nleft = count;
  23.     ssize_t nread;
  24.     char *bufp =(char*)buf;
  25.     while(nleft>0)
  26.     {
  27.         if((nread =read(fd,bufp,nleft))<0)
  28.         {
  29.             if(errno ==EINTR)
  30.                 continue;
  31.             return -1;
  32.         }
  33.         else if(nread ==0)
  34.             return count - nleft;
  35.             
  36.         bufp +=nread;
  37.         nleft -=nread;
  38.         
  39.     }
  40.     return count;
  41. }
  42. ssize_t writen(int fd,const void*buf,size_t count) ///用writen函数,防止在广域网上发生粘包
  43. {
  44.     size_t nleft=count;
  45.     ssize_t nwritten;
  46.     char *bufp=(char*)buf;
  47.     while(nleft>0)
  48.     {
  49.         if((nwritten =write(fd,bufp,nleft))<0)
  50.         {
  51.             if(errno ==EINTR)
  52.                 continue;
  53.             return -1;
  54.         }
  55.         else if(nwritten ==0)
  56.             continue;
  57.             
  58.         bufp +=nwritten;
  59.         nleft -=nwritten;
  60.         
  61.     }
  62.     return count;
  63. }

  64. int main()
  65. {
  66.     ///定义sockfd
  67.      int sock= socket(AF_INET,SOCK_STREAM, 0);
  68.      if (sock<0)
  69.         
  70.          {
  71.         perror("sock");
  72.         exit(1);
  73.     }
  74.     struct sockaddr_in servaddr;
  75.     memset(&servaddr,0,sizeof(servaddr));


  76.     ///定义sockaddr_in
  77.     
  78.     servaddr.sin_family = AF_INET;
  79.     servaddr.sin_port = htons(MYPORT);
  80.     servaddr.sin_addr.s_addr = inet_addr("127.0.0.2");

  81.     ///bind,成功返回0,出错返回-1
  82.     
  83.    if (connect(sock,(struct sockaddr*)&servaddr,sizeof(servaddr))<0)
  84.      {
  85.         perror("connect");
  86.         exit(1);
  87.         } ///获得IP地址和端口
  88.          printf("ip=%s port=%d\n",inet_ntoa(servaddr.sin_addr),ntohs(servaddr.sin_port));
  89.     struct packet sendbuf;
  90.     struct packet recvbuf;
  91.     memset(&sendbuf,0,sizeof(sendbuf));
  92.     memset(&recvbuf,0,sizeof(recvbuf));
  93.     int n;
  94.      while (fgets(sendbuf.buf, sizeof(sendbuf.buf), stdin) != NULL) ///键盘输入
  95.     {
  96.             n=strlen(sendbuf.buf);
  97.             sendbuf.len=htonl(n);
  98.          writen(sock,&sendbuf,4+n);
  99.             int ret = readn(sock, &recvbuf.len, 4);
  100.         if (ret ==-1)
  101.         {
  102.         perror("read");
  103.         exit(1);
  104.         }
  105.         else if(ret <4)
  106.         {
  107.             printf("client close\n");
  108.         
  109.             break;
  110.         }
  111.         n=ntohl(recvbuf.len);
  112.         ret =readn(sock,recvbuf.buf,n);
  113.         if (ret ==-1)
  114.         {
  115.         perror("read");
  116.         exit(1);
  117.         }
  118.         else if(ret <n)
  119.         {
  120.             printf("client close\n");
  121.         
  122.             break;
  123.         }
  124.         
  125.         fputs(recvbuf.buf,stdout);
  126.         memset(&sendbuf,0,sizeof(sendbuf));
  127.         memset(&recvbuf,0,sizeof(recvbuf));
  128.     }
  129.     close(sock);
  130.     return 0;
  131. }

阅读(1446) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~