Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1062288
  • 博文数量: 77
  • 博客积分: 821
  • 博客等级: 军士长
  • 技术积分: 1905
  • 用 户 组: 普通用户
  • 注册时间: 2011-10-23 16:17
个人简介

学校:上海交通大学软件工程 学历:硕士 行业:从事流媒体移动开发 QQ: 412595942 邮箱:yiikai1987910@gmail.com

文章分类

全部博文(77)

文章存档

2016年(4)

2015年(15)

2014年(16)

2013年(12)

2012年(21)

2011年(9)

分类: C/C++

2011-11-08 13:04:07

    最近工作需要,研究了下rtsp协议的传输方式,当然了现在只是入门,以后会陆续添加工作中的所学。
    rtsp是通过socket通信从而与rtsp流服务器就行数据交互的,详细的下一次在记录。借这次机会顺便研究了下unix网络编程,特此在这记录自己的一个小小的网络编程例子......
1 .   server.c
  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/socket.h>
  4. #include <netinet/in.h>
  5. #include <strings.h>
  6. #include <stdlib.h>
  7. #include <arpa/inet.h>
  8. int main(int argc,char **argv)
  9. {
  10.     struct sockaddr_in sevAddr; 
  11.     struct sockaddr_in cliAddr;
  12.     struct sockaddr_in copyAddr;
  13. //以上三个sockaddr_in结构体代表的IPV4协议簇,
  14.     bzero(&sevAddr,sizeof(sevAddr));
  15. //bzero是专门设计的一个对给定结构体中的元素置0的接口,类似于初始化
  16.     sevAddr.sin_family = AF_INET;  //AF_INET代表的是传输协议是tcp,udp,etc
  17.     sevAddr.sin_addr.s_addr = inet_addr("192.168.0.114");//inet_addr函数是将字符串转换成网络字节序的ip地址格式
  18. //对于IP地址的设定还可以不用固定的ip绑定,而让操作系统自己去找,这部分以后在说
  19.     sevAddr.sin_port = htons(36988);
  20. //以上三个是对server机器的地址端口号设定
  21. //这里注意到了htons()这个函数,作用是把本地字节序的数据转成网络字节序
  22. //htons,htonl,ntohs,ntohl这几个函数,前两个是本地转网络,后两个是网络转本地
  23. //s和l分别代表了short和long,所以可以注意到端口号用的是s,ip地址用的是l
  24.     int sev_fd,cli_fd;   
  25.     int resault;
  26.     pid_t childPid;
  27.     socklen_t cliAddrSize = sizeof(cliAddr);
  28.     sev_fd = socket(AF_INET,SOCK_STREAM,0);   //创建套接字,这里注意到AF_INET和SOCK_STREAM搭配,这表示用的是IPV4的传输协议
  29.     if(-1 == sev_fd)
  30.     {
  31.         printf("socket set up fail,please check it\n");
  32.         return 0;
  33.     }
  34.     resault = bind(sev_fd,(const struct sockaddr*)(&sevAddr),sizeof(sevAddr)); //绑定套接字到本机地址
  35.     if(-1 == resault)
  36.     {
  37.         printf("bind socket error ,please check it\n");
  38.         return 0;
  39.     }
  40.     socklen_t copyAddrSize = sizeof(copyAddr);
  41.     resault = getsockname(sev_fd,(struct sockaddr*)(&copyAddr),&copyAddrSize);//getsockname可以获取绑定在套接字上的地址信息
  42.     if(-1 == resault)
  43.     {
  44.         printf("get sockaddr info error\n");
  45.     }
  46.     printf("port is %u\n",ntohs(copyAddr.sin_port));
  47.     printf("ip is %u\n",ntohl(copyAddr.sin_addr.s_addr));
  48.     resault = listen(sev_fd,3);  //监听改服务器套接字,看有否有客户端链接上来
  49.     if(-1 == resault)
  50.     {
  51.         printf("listen the socket fail,please check it\n");
  52.         return 0;
  53.     }

  54.     while(1)
  55.     {
  56.         cli_fd = accept(sev_fd,(struct sockaddr*)(&cliAddr),&(cliAddrSize));  //接受客户端的请求,这个接口可以顺便获得client的套接字,地址信息,端口号信息等等
  57.         if(-1 == cli_fd)
  58.         {
  59.             printf("accept client connect error,please check it\n");
  60.         }
  61.         if((childPid = fork()) == 0)   //构建子进程为了实现并发服务器的作用
  62.         {
  63.             close(sev_fd);    //关闭监听套接字
  64.             printf("client ip is %u\n",ntohl(cliAddr.sin_addr.s_addr));
  65.             printf("client port is %u\n",ntohs(cliAddr.sin_port));
  66.             int i =0;
  67.             for(;i<10;i++)
  68.             {
  69.                 printf(".\n");
  70.                 sleep(1);
  71.             }
  72.             exit(0);
  73.         }
  74.         close(cli_fd);  //关闭客户端套接字
  75.     }
  76. }
简单了来说,server的流程其实就是:套接字创建->绑定套接字到指定地址->接听套接字->接受客户端的请求
详细的专业术语这里就不多说了,关键的部分在代码中都做了注释.

2.  client
  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/socket.h>
  4. #include <netinet/in.h>
  5. #include <strings.h>
  6. #include <stdlib.h>
  7. #include <arpa/inet.h>

  8. int main(int argc ,char **argv)
  9. {
  10.     if(argc < 2)
  11.     {
  12.         printf("the argv is not enough\n");
  13.         return 0;
  14.     }
  15.     int cli_fd;
  16.     struct sockaddr_in sevaddr;
  17.     sevaddr.sin_family = AF_INET;
  18.     sevaddr.sin_port = htons(36988);
  19.     sevaddr.sin_addr.s_addr = inet_addr(argv[1]);
  20. //以上设置server地址信息
  21.     cli_fd = socket(AF_INET,SOCK_STREAM,0);
  22.     if(-1 == cli_fd)
  23.     {
  24.         printf("client socket set up fail,please check it\n");
  25.         return 0;
  26.     }
  27.     int resault;
  28.     resault = connect(cli_fd,(struct sockaddr*)(&sevaddr),sizeof(sevaddr));   //链接服务器
  29.     if(-1 == resault)
  30.     {
  31.         printf("connect the server fail,please check it\n");
  32.         return 0;
  33.     }
  34.     return 0;
  35. }
client就相对简单了:建立套接字->链接服务器

   接下来说一说INADDR_ANY这个参数的作用,在设定主机服务器ip地址的时候,不同过绑定指定ip的话可以用这个方法来绑定,这个参数的意思就是说任何服务器所带的ip地址接受到的数据都由这个服务器程序来接管。为什么这么说呢?因为很多时候可能服务器有不止一个网卡,那这么一来服务器就有多个IP,所以只要是发到这个服务器上的ip的数据,程序就都能截获了!

   今天研究了下网络编程中的IO口复用技术,特此总结下:
    先上代码:
1. server:
  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/socket.h>
  4. #include <netinet/in.h>
  5. #include <strings.h>
  6. #include <stdlib.h>
  7. #include <arpa/inet.h>
  8. #include <sys/select.h>
  9. #include <string.h>
  10. int main(int argc,char **argv)
  11. {
  12.     struct sockaddr_in sevAddr;
  13.     struct sockaddr_in cliAddr;
  14.     struct sockaddr_in copyAddr;
  15.     bzero(&sevAddr,sizeof(sevAddr));
  16.     sevAddr.sin_family = AF_INET;
  17.     //sevAddr.sin_addr.s_addr = inet_addr("192.168.0.114");
  18.     sevAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  19.     sevAddr.sin_port = htons(36988);
  20.     int sev_fd,cli_fd;
  21.     int resault;
  22.     pid_t childPid;
  23.     socklen_t cliAddrSize = sizeof(cliAddr);
  24.     sev_fd = socket(AF_INET,SOCK_STREAM,0);
  25.     if(-1 == sev_fd)
  26.     {
  27.         printf("socket set up fail,please check it\n");
  28.         return 0;
  29.     }
  30.     resault = bind(sev_fd,(const struct sockaddr*)(&sevAddr),sizeof(sevAddr));
  31.     if(-1 == resault)
  32.     {
  33.         printf("bind socket error ,please check it\n");
  34.         return 0;
  35.     }
  36.     socklen_t copyAddrSize = sizeof(copyAddr);
  37.     resault = getsockname(sev_fd,(struct sockaddr*)(&copyAddr),&copyAddrSize);
  38.     if(-1 == resault)
  39.     {
  40.         printf("get sockaddr info error\n");
  41.     }
  42.     printf("port is %u\n",ntohs(copyAddr.sin_port));
  43.     printf("ip is %u\n",ntohl(copyAddr.sin_addr.s_addr));
  44.     resault = listen(sev_fd,3);
  45.     if(-1 == resault)
  46.     {
  47.         printf("listen the socket fail,please check it\n");
  48.         return 0;
  49.     }

  50.     //设置IO复用的select参数属性
  51.     fd_set readSet;
  52.     struct timeval waitTime;
  53.     waitTime.tv_sec = 2;
  54.     waitTime.tv_usec = 0;
  55.     int client[FD_SETSIZE];
  56.     int i;
  57.     char recvbuf[100];
  58.     int maxi = -1; //记录在client[]中的客户端描述符数
  59.     for(i = 0;i<FD_SETSIZE;i++)
  60.     {
  61.         client[i] = -1;
  62.     }
  63.     FD_SET(sev_fd,&readSet);
  64.     int maxfd = sev_fd; //监听的描述符的最大数
  65.     printf("the first maxfd is %d\n",sev_fd);    
  66.     ////////////////////////////////////////
  67.     while(1)
  68.     {
  69.         waitTime.tv_sec = 2;
  70.         waitTime.tv_usec = 0;
  71.         FD_SET(sev_fd,&readSet);
  72.         maxfd = sev_fd;
  73.         for(i=0;i<FD_SETSIZE;i++)
  74.         {
  75.             if(client[i]!= -1)
  76.             {
  77.                 FD_SET(client[i],&readSet);
  78.                 maxi = (i+1);
  79.                 if(client[i] > maxfd)
  80.                 {
  81.                     maxfd = client[i];
  82.                 }
  83.             }
  84.         }
  85.         
  86.         switch(select(maxfd+1,&readSet,NULL,NULL,&waitTime))
  87.         {
  88.             case -1:
  89.                 {
  90.                     printf("set select error,please check it\n");
  91.                     return 0;
  92.                 }break;
  93.             case 0:
  94.                 {
  95.                     printf("no client start to read\n");
  96.                 }break;
  97.             default:
  98.                 {
  99.                     if(FD_ISSET(sev_fd,&readSet))
  100.                     {
  101.                         //有新的客户端需要连接
  102.                         cli_fd = accept(sev_fd,(struct sockaddr*)(&cliAddr),&(cliAddrSize));
  103.                         if(-1 == cli_fd)
  104.                         {
  105.                             printf("accept client connect error,please check it\n");
  106.                             return 0;
  107.                         }
  108.                         printf("cli_fd is %d\n",cli_fd);
  109.                         for( i = 0;i<FD_SETSIZE;i++)
  110.                         {
  111.                             if(client[i] == -1)
  112.                             {
  113.                                 client[i] = cli_fd;
  114.                                 maxi = (i+1);
  115.                                 if(client[i] > maxfd)
  116.                                 {
  117.                                     maxfd = client[i];
  118.                                 }
  119.                                 break;        
  120.                             }
  121.                         }
  122.                         FD_SET(cli_fd,&readSet);
  123.                     }
  124.                     for(i=0;i<maxi;i++)
  125.                     {
  126.                         if(client[i] < -1)
  127.                         {
  128.                             //printf("no client is perpaer for the readn\n");
  129.                             continue;
  130.                         }
  131.                         if(FD_ISSET(client[i],&readSet))
  132.                         {
  133.                             memset(recvbuf,0,sizeof(recvbuf));
  134.                             printf("I have a client : %d\n",client[i]);
  135.                             recvfrom(client[i],recvbuf,sizeof(recvbuf),0,NULL,NULL);
  136.                             printf("recv the message from client is %s\n",recvbuf);
  137.                             close(client[i]);
  138.                             FD_CLR(client[i],&readSet);
  139.                             client[i]=-1;
  140.                             //对客户端描述符的读操作
  141.                         }

  142.                 }
  143.         }
  144.         /*
  145.         resault = select(maxfd+1,&readSet,NULL,NULL,&waitTime);
  146.         if(-1 == resault)
  147.         {
  148.             printf("set select error,please check it\n");
  149.             return 0;
  150.         }
  151.         if( 0 == resault)
  152.         {
  153.             //printf("no client has start read\n");
  154.             continue;
  155.         }
  156.         printf("select resault is %d.................\n",resault);
  157.         if(FD_ISSET(sev_fd,&readSet))
  158.         {
  159.             //有新的客户端需要连接
  160.             cli_fd = accept(sev_fd,(struct sockaddr*)(&cliAddr),&(cliAddrSize));
  161.             if(-1 == cli_fd)
  162.             {
  163.                 printf("accept client connect error,please check it\n");
  164.                 return 0;
  165.             }
  166.             printf("cli_fd is %d\n",cli_fd);
  167.             for( i = 0;i<FD_SETSIZE;i++)
  168.             {
  169.                 if(client[i] == -1)
  170.                 {
  171.                     client[i] = cli_fd;
  172.                      maxi = (i+1);
  173.                     if(client[i] > maxfd)
  174.                     {
  175.                         maxfd = client[i];
  176.                     }
  177.                     break;        
  178.                 }
  179.             }
  180.             FD_SET(cli_fd,&readSet);
  181.         }
  182.         for(i=0;i<maxi;i++)
  183.         {
  184.             if(client[i] < -1)
  185.             {
  186.                 //printf("no client is perpaer for the readn\n");
  187.                 continue;
  188.             }
  189.             if(FD_ISSET(client[i],&readSet))
  190.             {
  191.                 memset(recvbuf,0,sizeof(recvbuf));
  192.                 printf("I have a client : %d\n",client[i]);
  193.                 recvfrom(client[i],recvbuf,sizeof(recvbuf),0,NULL,NULL);
  194.                 printf("recv the message from client is %s\n",recvbuf);
  195.                 close(client[i]);
  196.                 FD_CLR(client[i],&readSet);
  197.                 client[i]=-1;
  198.                 //对客户端描述符的读操作
  199.             }
  200.         }
  201.         */
  202.         }
  203.     }
  204. }


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