Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7893838
  • 博文数量: 701
  • 博客积分: 2150
  • 博客等级: 上尉
  • 技术积分: 13233
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-29 16:28
个人简介

天行健,君子以自强不息!

文章分类

全部博文(701)

文章存档

2019年(2)

2018年(12)

2017年(76)

2016年(120)

2015年(178)

2014年(129)

2013年(123)

2012年(61)

分类: LINUX

2012-02-29 16:50:35

前言
   socket编程现在几乎成了网络编程的代名词,关于这方面的书籍与资料更是不可胜数。比较好的可以推荐一下《Unix 网络编程 卷1:套接字联网API》。

1. TCP
   TCP提供客户与服务器之间的连接(connection),TCP客户先与某个给定服务器之间建立一个连接,再跨该连接与那个服务器交换数据,然后终止这个连接。
   
1.1 TCP server
编程步骤:
socket→初始化struct  sockaddr_in→bind→listen→[accept→send→recv]
tcp_server.c
  1. /*
  2.  * \brief
  3.  * tcp server
  4.  */
  5. #include <stdio.h>
  6. #include <sys/socket.h>
  7. #include <sys/types.h>
  8. #include <netinet/in.h>
  9. #include <arpa/inet.h>
  10. #include <string.h>
  11. #include <stdlib.h>

  12. #define SERVPORT 8080
  13. #define BACKLOG 10 // max numbef of client connection
  14. #define MAXDATASIZE 100

  15. int main(char argc, char *argv[])
  16. {
  17.   int sockfd, client_fd, addr_size, recvbytes;
  18.   char rcv_buf[MAXDATASIZE], snd_buf[MAXDATASIZE];
  19.   char* val;
  20.   struct sockaddr_in server_addr; 
  21.   struct sockaddr_in client_addr;

  22.   char IPdotdec[20];

  23.   /* create a new socket and regiter it to os .
  24.    * SOCK_STREAM means that supply tcp service,
  25.    * and must connect() before data transfort.
  26.    */
  27.   if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  28.   {
  29.     perror("socket:");
  30.     exit(1);
  31.   }

  32.   /* setting server's socket */
  33.   server_addr.sin_family = AF_INET;         // IPv4 network protocol
  34.   server_addr.sin_port = htons(SERVPORT);
  35.   server_addr.sin_addr.s_addr = INADDR_ANY; // auto IP detect
  36.   memset(&(server_addr.sin_zero),0, 8);

  37.   if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr))== -1)
  38.   {
  39.     perror("bind:");
  40.     exit(1);
  41.   }

  42.   /* watting for connection , and server permit to recive the requestion from sockfd */
  43.   if (listen(sockfd, BACKLOG) == -1) // BACKLOG assign thd max number of connection
  44.   {
  45.     perror("listen:");
  46.     exit(1);
  47.   }

  48.   while(1)
  49.   {
  50.     addr_size = sizeof(struct sockaddr_in);

  51.     /* accept the sockfd's connection,
  52.      * return an new socket and assign far host to client_addr
  53.      */
  54.     if ((client_fd = accept(sockfd, (struct sockaddr *)&client_addr, &addr_size)) == -1)
  55.     {
  56.       /* Nonblocking mode */
  57.       perror("accept:");
  58.       continue;
  59.     }

  60.     /* network-digital to ip address */
  61.     inet_ntop(AF_INET, (void*)&client_addr, IPdotdec, 16);
  62.     printf("connetion from:%d : %s\n",client_addr.sin_addr, IPdotdec);

  63.     if (!fork())
  64.     {
  65.       /* child process handle with the client connection */

  66.       /* recive the client's data by client_fd */
  67.       if ((recvbytes = recv(client_fd, rcv_buf, MAXDATASIZE, 0)) == -1)
  68.       {
  69.         perror("recv:");
  70.         exit(1);
  71.       }
  72.       rcv_buf[recvbytes]='\0';
  73.       printf("recv:%s\n", rcv_buf);


  74.       *snd_buf='\0';
  75.       strcat(snd_buf, "welcome");
  76.       /* send the message to far-hosts by client_fd */
  77.       if (send(client_fd, snd_buf, strlen(snd_buf), 0) == -1)
  78.       {
  79.         perror("send:");
  80.         exit(1);
  81.       }
  82.       printf("send:%s\n", snd_buf);

  83.       close(client_fd);
  84.       exit(1);
  85.     }

  86.     close(client_fd);
  87.   }

  88.   return 0;
  89. }
编译:
  1. gcc -g -o tcp_server tcp_server.c
1.2 TCP client
编程步骤:
socket→初始化struct  sockaddr_in→connect→[recv→send]
tcp_client.c
  1. /*
  2.  * \brief
  3.  * tcp client
  4.  */

  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <sys/socket.h>
  8. #include <netdb.h>
  9. #include <string.h>

  10. #define SERVPORT 8080
  11. #define MAXDATASIZE 100

  12. int main(int argc, char *argv[])
  13. {
  14.   int sockfd, recvbytes;
  15.   char rcv_buf[MAXDATASIZE]; /*./client 127.0.0.1 hello */
  16.   char snd_buf[MAXDATASIZE];
  17.   struct hostent *host;             /* struct hostent
  18.                                      * {
  19.                                      * char *h_name; // general hostname
  20.                                      * char **h_aliases; // hostname's alias
  21.                                      * int h_addrtype; // AF_INET
  22.                                      * int h_length;
  23.                                      * char **h_addr_list;
  24.                                      * };
  25.                                      */
  26.   struct sockaddr_in server_addr;

  27.   if (argc < 3)
  28.   {
  29.     printf("Usage:%s [ip address] [any string]\n", argv[0]);
  30.     return 1;
  31.   }

  32.   *snd_buf = '\0';
  33.   strcat(snd_buf, argv[2]);

  34.   if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  35.   {
  36.     perror("socket:");
  37.     exit(1);
  38.   }

  39.   server_addr.sin_family = AF_INET;
  40.   server_addr.sin_port = htons(SERVPORT);
  41.   inet_pton(AF_INET, argv[1], &server_addr.sin_addr);
  42.   memset(&(server_addr.sin_zero), 0, 8);

  43.   /* create the connection by socket
  44.    * means that connect "sockfd" to "server_addr"
  45.    */
  46.   if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
  47.   {
  48.     perror("connect");
  49.     exit(1);
  50.   }

  51.   /**/
  52.   if (send(sockfd, snd_buf, sizeof(snd_buf), 0) == -1)
  53.   {
  54.     perror("send:");
  55.     exit(1);
  56.   }
  57.   printf("send:%s\n", snd_buf);

  58.   if ((recvbytes = recv(sockfd, rcv_buf, MAXDATASIZE, 0)) == -1)
  59.   {
  60.     perror("recv:");
  61.     exit(1);
  62.   }

  63.   rcv_buf[recvbytes] = '\0';
  64.   printf("recv:%s\n", rcv_buf);

  65.   close(sockfd);
  66.   return 0;
  67. }
编译:
  1. gcc -o -g tcp_client tcp_client.c
2. UDP
   UDP提供无连接的(connectionless)服务,比如一个UDP客户可以创建一个套接字并发送一个数据报给一个给定的服务器,然后立即用同一个套接字发送另一个数据报给另一个服务器。同样地,一个UDP服务器可以用同一个UDP套接字从若干不同的客户接收数据报,每个客户一个数据报。

2.1 UDP server
编程步骤:
socket→初始化struct  sockaddr_in→bind→[recvfrom→sendto]
udp_server.c
  1. #include <stdio.h>
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. #include <string.h>
  5. #include <stdlib.h>


  6. #define SERVPORT 8080
  7. #define MAXDATASIZE 100

  8. int main()
  9. {
  10.   int sockfd, addr_size, recvbytes;
  11.   char rcv_buf[MAXDATASIZE], snd_buf[MAXDATASIZE];
  12.   char* val;
  13.   struct sockaddr_in server_addr;

  14.   if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
  15.   {
  16.     perror("socket:");
  17.     exit(1);
  18.   }

  19.   server_addr.sin_family = AF_INET;
  20.   server_addr.sin_port = htons(SERVPORT);
  21.   server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  22.   memset(&(server_addr.sin_zero), 0, 8);

  23.   if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))==-1)
  24.   {
  25.     perror("bind:");
  26.     exit(1);
  27.   }

  28.   while(1)
  29.   {
  30.     addr_size = sizeof(struct sockaddr);

  31.     /* receive the data from "server_addr" by "sockfd" and store into "rcv_buf" */
  32.     if ((recvbytes = recvfrom(sockfd, rcv_buf, MAXDATASIZE, 0,
  33.               (struct sockaddr*)&server_addr, &addr_size)) == -1)
  34.     {
  35.       perror("recv:");
  36.       exit(1);
  37.     }
  38.     rcv_buf[recvbytes] = '\0';
  39.     printf("recv:%s : %s\n", inet_ntop(server_addr.sin_addr), rcv_buf);

  40.     *snd_buf = '\0';
  41.     strcat(snd_buf, "welcome");

  42.     /* send the data "snd_buf" to "server_addr" by "sockfd" */
  43.     if (sendto(sockfd, snd_buf, strlen(snd_buf), 0,
  44.             (struct sockaddr*)&server_addr, addr_size) == -1)
  45.     {
  46.       perror("send:");
  47.       exit(1);
  48.     }
  49.     printf("send:%s\n", snd_buf);
  50.     //exit(1);
  51.   }
  52.   close(sockfd);
  53.   return 0;
  54. }
编译:
  1. gcc -g -o udp_server udp_server.c
2.2 UDP client
编程步骤:
socket→初始化struct  sockaddr_in→[sendto→recvfrom]
udp_client.c
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/socket.h>
  4. #include <netdb.h>
  5. #include <string.h>

  6. #define SERVPORT 8080
  7. #define MAXDATASIZE 100

  8. int main(int argc, char *argv[])
  9. {
  10.   int server_sockfd, recvbytes,addr_size;
  11.   char rcv_buf[MAXDATASIZE]; /*./client 127.0.0.1 hello*/
  12.   char snd_buf[MAXDATASIZE];
  13.   struct hostent *host;
  14.   struct sockaddr_in server_addr;

  15.   if (argc < 3)
  16.   {
  17.     printf("Usage:%s [ip address] [any string]\n",argv[0]);
  18.     return 1;
  19.   }
  20.   *snd_buf = '\0';
  21.   strcat(snd_buf,argv[2]);

  22.   if ((server_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
  23.   {
  24.     perror("socket:");
  25.     exit(1);
  26.   }

  27.   server_addr.sin_family=AF_INET;
  28.   server_addr.sin_port=htons(SERVPORT);
  29.   inet_pton(AF_INET,argv[1],&server_addr.sin_addr);
  30.   memset(&(server_addr.sin_zero),0,8);
  31.   addr_size=sizeof(struct sockaddr);

  32.   /* send the data "snd_buf" to "server_addr" by server_sockfd */
  33.   if (sendto(server_sockfd,snd_buf,sizeof(snd_buf),0,
  34.           (struct sockaddr*)&server_addr,addr_size) == -1)
  35.   {
  36.     perror("send:");
  37.     exit(1);
  38.   }
  39.   printf("send:%s\n",snd_buf);

  40.   /* receive the data from "server_addr" by "server_sockfd" and store into rcv_buf */
  41.   if ((recvbytes=recvfrom(server_sockfd,rcv_buf,MAXDATASIZE,0,
  42.             (struct sockaddr*)&server_addr,&addr_size)) ==-1)
  43.   {
  44.     perror("recv:");
  45.     exit(1);
  46.   }
  47.   rcv_buf[recvbytes] = '\0';
  48.   printf("recv:%s\n",rcv_buf);

  49.   close(server_sockfd);
  50.   return 0;
  51. }
编译:
  1. gcc -g -o udp_client udp_client.c
3. UDP multicast
  有时候,本机不止有一张网卡,所以接收UDP组播的数据先要将本机指定的网卡地址加入组播组,才能接收到组播数据。
编程步骤:
socket-->setsockopt-->bind->setsockopt(本机网卡加入组播组)-->[recvfrom --> sendto]
udp_multicast_recv.c
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <sys/socket.h>
  5. #include <sys/types.h>
  6. #include <netinet/in.h>
  7. #include <arpa/inet.h>

  8. #define UDPMCASTPORT 1234
  9. #define MAXDATASIZE 1024



  10. int main(char argc, char *argv[])
  11. {
  12.   int udp_sockfd, addr_size, recvbytes;
  13.   char rcv_buf[MAXDATASIZE];

  14.   struct sockaddr_in servaddr, clitaddr;
  15.   struct ip_mreq mreq;

  16.   char* pc_udpmcaddr = "225.1.1.31";
  17.   char* pc_udpmcport = "1234";
  18.   char* pc_localaddr = "192.168.1.73";
  19.   int i_reuse_socket;


  20.   if (argc != 3)
  21.   {
  22.     fprintf(stdout, "SYNTAX: ./udp_mcast_recv \n");
  23.     exit(1);
  24.   }
  25.   else
  26.   {
  27.     pc_udpmcaddr = argv[1];
  28.     pc_localaddr = argv[2];
  29.   }

  30.   memset(&servaddr, 0, sizeof(struct sockaddr_in));
  31.   memset(&clitaddr, 0, sizeof(struct sockaddr_in));
  32.   memset(&mreq, 0, sizeof(struct ip_mreq));

  33.   /* create socket */
  34.   if ((udp_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
  35.   {
  36.     perror("socket:");
  37.     exit(1);
  38.   }

  39.   i_reuse_socket = 1;
  40.   if (setsockopt(udp_sockfd, SOL_SOCKET, SO_REUSEADDR, &i_reuse_socket, sizeof(int))== -1)
  41.   {
  42.     perror("setsockopt:");
  43.     exit(1);
  44.   }

  45.   servaddr.sin_family = AF_INET;
  46.   servaddr.sin_port = htons(UDPMCASTPORT);

  47.   if (!inet_aton(pc_udpmcaddr, &servaddr.sin_addr))
  48.   {
  49.     perror("inet_aton:");
  50.     exit(1);
  51.   }
  52.   if (bind(udp_sockfd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr))==-1)
  53.   {
  54.     perror("bind:");
  55.     exit(1);
  56.   }

  57.   if (!inet_aton(pc_udpmcaddr, &mreq.imr_multiaddr))
  58.   {
  59.     perror("inet_aton:");
  60.     exit(1);
  61.   }

  62.   if (!inet_aton(pc_localaddr, &mreq.imr_interface))
  63.   {
  64.     perror("inet_aton:");
  65.     exit(1);
  66.   }

  67.   if (setsockopt(udp_sockfd, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))==-1)
  68.   {
  69.     perror("setsockopt:");
  70.     exit(1);
  71.   }

  72.   addr_size = sizeof(struct sockaddr);

  73.   while(1)
  74.   {
  75.     if ((recvbytes = recvfrom(udp_sockfd, rcv_buf, MAXDATASIZE, 0,
  76.               (struct sockaddr*)&clitaddr, &addr_size)) == -1)
  77.     {
  78.       perror("recvfrom:");
  79.       exit(1);
  80.     }
  81.     rcv_buf[recvbytes] = '\0';
  82.     fprintf(stdout, "recvfrom:%s:%s", inet_ntoa(clitaddr.sin_addr), rcv_buf);
  83.   }
  84. }
编译:
  1. gcc -g -o udp_multicast_recv udp_multicast_recv.c


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