当前位置:   article > 正文

基于UDP 实现客户端之间通信【2】_udp模式下,客户端之间相互通信吗

udp模式下,客户端之间相互通信吗

在写面向UDP连接的 socket 的通信程序时,我先总结归纳一些关于面向TCP和UDP连接的socket 通信程序的相关知识:

面向TCP连接的 socket 通信程序:

服务端:创建套接字,指定协议族(sockaddr_in),绑定,监听,接受连接,发送或接受数据,关闭连接;

        客户端:创建套接字,指定协议族,连接(connect),发送或接受数据,关闭连接;

TCP在接受数据时:write/send/sendto, read/recv/recvfrom都可以用, 通常会用send, recv;

但在面向UDP的socket程序中,发送数据时用sendto的话,就不用connect了,但是在面向TCP的程序中

,在发送数据时,即使用sendto,也必须用connect

面向UDP连接的socket通信程序:

服务端:创建套接字,指定协议族(sockaddr_in),绑定(不需要listen和accept),发送或接收数据;

客户端:创建套接字,指定协议族,连接(和TCP的客户端步骤一样),发送或接受数据;

UDP常用sendto,recvfrom; 注意:用sendto时,就不用connect了(用了也没事),其他的(write, send)

必须用connect;

补充:1、无论是TCP还是UDP,默认情况下创建的都是阻塞模式的套接字,执行到(accept,connect, write/send/sento,read/recv/recvfrom)

  等语句时,会一直等待(connect)有点列外,它连接一段时间,如果连接不成功,会以错误形式返回,不会一直等待

    2、可以把socket设置成非阻塞模式, Linux下用fcntl函数,TCP和UDP设置成非阻塞模式以后,效果是一样的,都不再等待

  而是立即返回

    3、TCP面向连接, UDP面向无连接

   TCP:客户端退出程序时或断开连接时,TCP的这个函数会立即返回不在阻塞(因为服务端自己知道客户端已经退出或断开连接,证明它是面向连接的)

                   UDP:始终保持阻塞(服务端不知道客户端已经退出或断开连接,证明它是面向无连接的)

            4、TCP无边界,UDP有边界

   TCP:客户端连续发送数据,只要服务端的这个函数的缓冲区足够大,会一次性接收过来

     (客户端是分好几次发过来,是有边界的,而服务端却一次性接收过来,所以证明是无边界的)

           UDP:客户端连续发送数据,即使服务端的这个函数的缓冲区足够大,也只会一次一次的接收,客户端分

几次发送过来,服务端就必须按几次接收

补充:

    1、socket()的参数不同

            2、UDP Server不需要调用listen和accept

    3、UDP收发数据用sendto/recvfromhanshu

            4、UDP:shutdown函数无效

            5、TCP:地址信息在connect/accept时确定     UDP:在sendto/recvfrom函数中每次均需指定地址信息

                  Sendto()和recvfrom()用于在无连接的数据报socket方式下进行数据传输。由于本地socket并没有与远端机器

                  进行连接,所以在发送数据时应指明目的地址


下面就是我写的利用UDP连接和多线程实现的客户端之间的通信代码:

服务器端:UdpServer.c

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/socket.h>
  4. #include <sys/socket.h>
  5. #include <netinet/in.h>
  6. #include <arpa/inet.h>
  7. #include <string.h>
  8. #include <stdlib.h>
  9. #define PORT 8888
  10. struct info
  11. {
  12. char buf[100];
  13. int port;
  14. };
  15. int main()
  16. {
  17. int sockfd, length, ret, j, i = 0;
  18. struct sockaddr_in server_addr;
  19. struct sockaddr_in client_addr[10] = {0};
  20. struct sockaddr_in tmp_addr;
  21. struct info RecvBuf = {0};
  22. sockfd = socket(PF_INET, SOCK_DGRAM, 0);
  23. if (-1 == sockfd)
  24. {
  25. perror("socket");
  26. exit(1);
  27. }
  28. bzero(&server_addr, sizeof(server_addr));
  29. server_addr.sin_family = AF_INET;
  30. server_addr.sin_port = PORT;
  31. server_addr.sin_addr.s_addr = inet_addr("192.168.0.128");
  32. ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
  33. if (ret < 0)
  34. {
  35. perror("bind");
  36. exit(1);
  37. }
  38. while (1)
  39. {
  40. length = sizeof(client_addr[0]);
  41. ret = recvfrom(sockfd, &RecvBuf, sizeof(RecvBuf), 0, (struct sockaddr *)&tmp_addr, &length);
  42. if (ret < 0)
  43. {
  44. perror("recvfrom");
  45. exit(1);
  46. }
  47. printf("Recv From Client %d : %s\n", tmp_addr.sin_port, RecvBuf.buf);
  48. if (0 == i)
  49. {
  50. client_addr[0].sin_family = tmp_addr.sin_family;
  51. client_addr[0].sin_port = tmp_addr.sin_port;
  52. client_addr[0].sin_addr.s_addr = tmp_addr.sin_addr.s_addr;
  53. i++;
  54. }
  55. else
  56. {
  57. for (j = 0; j < i; j++)
  58. {
  59. if (tmp_addr.sin_port == client_addr[j].sin_port)
  60. {
  61. break;
  62. }
  63. if (j == i - 1)
  64. {
  65. client_addr[i].sin_family = tmp_addr.sin_family;
  66. client_addr[i].sin_port = tmp_addr.sin_port;
  67. client_addr[i].sin_addr.s_addr = tmp_addr.sin_addr.s_addr;
  68. i++;
  69. }
  70. }
  71. }
  72. if (!strcmp(RecvBuf.buf, "bye"))
  73. {
  74. break;
  75. }
  76. strcat(RecvBuf.buf, "-server");
  77. for(j = 0; j < i; j++)
  78. {
  79. if (RecvBuf.port == client_addr[j].sin_port)
  80. {
  81. break;
  82. }
  83. if (j == i - 1)
  84. {
  85. break;
  86. }
  87. }
  88. ret = sendto(sockfd, &RecvBuf, sizeof(RecvBuf), 0, (struct sockaddr *)&client_addr[j], sizeof(client_addr[0]));
  89. if (ret < 0)
  90. {
  91. perror("sendto");
  92. exit(1);
  93. }
  94. memset(&RecvBuf, 0, sizeof(RecvBuf));
  95. }
  96. close(sockfd);
  97. return 0;
  98. }
客户端:UdpClient.c


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <sys/types.h>
  5. #include <sys/socket.h>
  6. #include <sys/socket.h>
  7. #include <netinet/in.h>
  8. #include <arpa/inet.h>
  9. #define PORT 8888
  10. struct info
  11. {
  12. char buf[100];
  13. int port;
  14. };
  15. void *Send(void *arg)
  16. {
  17. struct info SendBuf = {0};
  18. struct sockaddr_in server_addr;
  19. int ret;
  20. bzero(&server_addr, sizeof(server_addr));
  21. server_addr.sin_family = PF_INET;
  22. server_addr.sin_port = PORT;
  23. server_addr.sin_addr.s_addr = inet_addr("192.168.0.128");
  24. while(1)
  25. {
  26. scanf("%s %d", SendBuf.buf, &SendBuf.port);
  27. ret = sendto(*(int *)arg, &SendBuf, sizeof(SendBuf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
  28. if (ret < 0)
  29. {
  30. perror("sendto");
  31. exit(1);
  32. }
  33. if (!strcmp(SendBuf.buf, "bye"))
  34. {
  35. break;
  36. }
  37. bzero(&SendBuf, sizeof(SendBuf));
  38. }
  39. }
  40. void *Recv(void *arg)
  41. {
  42. struct info RecvBuf = {0};
  43. int length;
  44. struct sockaddr_in server_addr;
  45. int ret;
  46. while (1)
  47. {
  48. length = sizeof(server_addr);
  49. ret = recvfrom(*(int *)arg, &RecvBuf, sizeof(RecvBuf), 0, (struct sockaddr *)&server_addr, &length);
  50. if (ret < 0)
  51. {
  52. perror("recvfrom");
  53. exit(1);
  54. }
  55. printf("Recv From Server : %s\n", RecvBuf.buf);
  56. }
  57. }
  58. int main()
  59. {
  60. int sockfd, ret, length;
  61. struct info SendBuf = {0};
  62. pthread_t tid[2];
  63. sockfd = socket(PF_INET, SOCK_DGRAM, 0);
  64. if (-1 == sockfd)
  65. {
  66. perror("sockt");
  67. exit(1);
  68. }
  69. ret = pthread_create(&tid[0], NULL, Send, (void *)&sockfd);
  70. if (ret < 0)
  71. {
  72. perror("pthread_create");
  73. exit(1);
  74. }
  75. ret = pthread_create(&tid[1], NULL, Recv, (void *)&sockfd);
  76. if (ret < 0)
  77. {
  78. perror("pthread_create");
  79. exit(1);
  80. }
  81. pthread_join(tid[0], NULL);
  82. pthread_join(tid[1], NULL);
  83. close(sockfd);
  84. return 0;
  85. }




声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号