[关闭]
@Dubyoo 2014-06-13T11:28:36.000000Z 字数 4294 阅读 3104

2014-04-02 Linux网络编程 - socket建立UDP连接

使用UDP协议的流程

  1. 服务端:socket ---> bind ---> recvfrom ---> sendto ---> close
  2. 客户端:socket -------------> sendto ---> recvfrom ---> close

1.socket

  1. /* socket:生成一个套接口描述符 */
  2. int socket(int domain, int type, int protocol);
  3. //domain ---> AF_INET: IPv4; AF_INET6: IPv6;
  4. //type ---> SOCK_STREAM: tcp; SOCK_DGRAM: udp;
  5. //protocol ---> 指定socket传输所用的协议编号,通常为0 。

2.bind

  1. /* bind:绑定一个端口号和ip地址,使套接口与端口号和ip地址相关联 */
  2. int bind(int sockfd, struct sockaddr * my_addr, int addrlen);
  3. // sockfd为前面socket的返回值。
  4. // my_addr为结构体指针变量,结构体如下
  5. // addrlen:sockaddr的结构体长度。通常是sizeof(struct sockaddr);
  6. struct sockaddr //此结构体不常用
  7. {
  8. unsigned short int sa_family; //调用socket()时的domain参数,即AF_INET值。
  9. char sa_data[14]; //最多使用14个字符长度
  10. };
  11. //使用ipv4时,其socketaddr结构定义便为
  12. struct sockaddr_in //常用的结构体
  13. {
  14. unsigned short int sin_family; //即为sa_family AF_INET
  15. uint16_t sin_port; //为使用的port编号
  16. struct in_addr sin_addr; //为IP 地址
  17. unsigned char sin_zero[8]; //未使用
  18. };
  19. struct in_addr
  20. {
  21. uint32_t s_addr;
  22. };
  1. /*bind实例*/
  2. struct sockaddr_in my_addr; //定义结构体变量
  3. memset(&my_addr, 0, sizeof(struct sockaddr)); //将结构体清空
  4. //或bzero(&my_addr, sizeof(struct sockaddr));
  5. my_addr.sin_family = AF_INET; //表示采用Ipv4网络协议
  6. my_addr.sin_port = htons(8888);
  7. //表示端口号为8888,通常是大于1024的一个值。
  8. //htons()用来将参数指定的16位hostshort转换成网络字符顺序
  9. my_addr.sin_addr.s_addr = inet_addr("192.168.1.13");
  10. // inet_addr()用来将IP地址字符串转换成网络所使用的二进制数字,如果为INADDR_ANY,这表示服务器自动填充本机IP地址。
  11. int iret = bind(sfd, (struct sockaddr*)&my_str, sizeof(struct socketaddr));
  12. if(iret == -1)
  13. {
  14. perror("bind");
  15. close(sfd);
  16. exit(-1);
  17. }

注:
my_addr.sin_port 置为 0,函数会自动为你选择一个未占用的端口来使用。
my_addr.sin_addr.s_addr 置为 INADDR_ANY,系统会自动填入本机IP地址。


3.recvfrom

  1. /* 从任意IP接收消息存入缓冲区,并将客户机IP放入内存 */
  2. int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);
  3. //sockfd: socket描述符
  4. //buf: 接收的字符串存入缓冲区buf中
  5. //len: 缓冲区长度
  6. //flags: 通常为0
  7. //from是一个struct sockaddr类型的变量,该变量保存连接机的IP地址及端口号。
  8. //fromlen常置为sizeof (struct sockaddr)。
  9. //当recvfrom()返回时,fromlen包含实际存入from中的数据字节数。

4.sendto

  1. /* 发送消息到指定IP */
  2. int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
  3. //sockfd: socket描述符
  4. //msg: 一般为常量字符串,发出的消息
  5. //len: msg长度
  6. //flags: 通常为0
  7. //to表示目地机的IP地址和端口号信息
  8. //tolen常常被赋值为sizeof (struct sockaddr)

5.close

  1. close(sock_fd) ;

实例

  1. /*server.c*/
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <sys/types.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <arpa/inet.h>
  8. #include <netinet/in.h>
  9. #include <sys/socket.h>
  10. int main(int argc, char * argv[]) // ---> ./server.exe [port]
  11. {
  12. int server_fd, iret ;
  13. char recv_buf[128], send_buf[128] ;
  14. struct sockaddr_in server_addr, client_addr ;
  15. // 1.socket
  16. server_fd = socket(AF_INET, SOCK_DGRAM, 0) ;
  17. if(server_fd == -1)
  18. {
  19. perror("socket");
  20. exit(-1) ;
  21. }
  22. // 2.bind
  23. memset(&server_addr, 0, sizeof(server_addr)) ;
  24. server_addr.sin_family = AF_INET ;
  25. server_addr.sin_port = htons(atoi(argv[1])) ;
  26. server_addr.sin_addr.s_addr = INADDR_ANY ;
  27. iret = bind(server_fd, (const struct sockaddr *)&server_addr, sizeof(server_addr)) ;
  28. if(iret == -1)
  29. {
  30. perror("bind") ;
  31. exit(-1) ;
  32. }
  33. // 3.recvfrom
  34. memset(&client_addr, 0, sizeof(client_addr)) ;
  35. memset(recv_buf, 0, 128) ;
  36. int len = sizeof(client_addr) ;
  37. recvfrom(server_fd, recv_buf, 128, 0, (struct sockaddr*)&client_addr, &len) ;
  38. char ip[32] = "" ;
  39. printf("receive from ip : %s, port : %d, message : %s\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), recv_buf) ;
  40. // 4.sendto
  41. memset(send_buf, 0, sizeof(client_addr)) ;
  42. strcpy(send_buf, "received !\n") ;
  43. sendto(server_fd, send_buf, strlen(send_buf), 0, (struct sockaddr*)&client_addr, sizeof(client_addr)) ;
  44. // 5.close
  45. close(server_fd) ;
  46. return 0;
  47. }
  1. /*client.c*/
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <sys/types.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <arpa/inet.h>
  8. #include <netinet/in.h>
  9. #include <sys/socket.h>
  10. int main(int argc, char * argv[]) // ---> ./exe [ip] [port]
  11. {
  12. int client_fd, iret ;
  13. char recv_buf[128], send_buf[128] ;
  14. struct sockaddr_in server_addr, client_addr ;
  15. // 1.socket
  16. client_fd = socket(AF_INET, SOCK_DGRAM, 0) ;
  17. if(client_fd == -1)
  18. {
  19. perror("socket") ;
  20. exit(-1) ;
  21. }
  22. memset(&server_addr, 0, sizeof(server_addr)) ;
  23. server_addr.sin_family = AF_INET ;
  24. server_addr.sin_port = htons(atoi(argv[2])) ;
  25. server_addr.sin_addr.s_addr = inet_addr(argv[1]) ;
  26. // 2.sendto
  27. memset(send_buf, 0, 128) ;
  28. strcpy(send_buf, "Hello guys !\n") ;
  29. sendto(client_fd, send_buf, strlen(send_buf), 0, (struct sockaddr*)&server_addr, sizeof(server_addr)) ;
  30. // 3.recvfrom
  31. memset(&server_addr, 0, sizeof(server_addr)) ;
  32. memset(recv_buf, 0, 128) ;
  33. int len = sizeof(server_addr) ;
  34. recvfrom(client_fd, recv_buf, 128, 0, (struct sockaddr*)&server_addr, &len) ;
  35. char ip[32] = "" ;
  36. printf("received form ip :%s, port : %d, message : %s\n", inet_ntoa(server_addr.sin_addr), ntohs(server_addr.sin_port), recv_buf) ;
  37. // 4.close
  38. close(client_fd) ;
  39. return 0 ;
  40. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注