前段时间发了个TCP通信的例子,现在再来一个UDP通信的例子。这些可以作为样本程序,用到开发中。“裸写”socket老是记不住步骤,经常被鄙视……

下面的例子很简单,写一个UDP的server用于收包,写一个UDP的client用于发包并接收来自server的回复。其中UDP的client写了两个,一个是不需要connect的,另一个是带上connect的,两个client实现的功能是一样的。从效率上,带上connect的UDP肯定效率稍微高一些。不过UDP的connect和TCP里面非常不一样。在UDP里面connect的时候并没有三次握手的过程,但是它指定了与自己通信的对方的具体地址,内核中会将次地址记录下来,如果你的UDP就是在确定了两台机器之间传送信息,建议选取带有connect的套接字。connect之后与对方通信直接write或者read函数就可以,不用再指定对方ip和port,并且connect之后的套接字可以自动过滤掉不是来自指定通信方的信息。UDP可以调用多次connect函数,但是TCP套接字只能调用一次,再次调用会出现错误。

1. 首先是服务端的程序:

UDPserver.cpp

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <unistd.h>
 4 #include <sys/types.h>
 5 #include <sys/socket.h>
 6 #include <stdlib.h>
 7 #include <netinet/in.h>
 8 #include <arpa/inet.h>
 9
10 #define PORT 1234
11 #define MAXDATASIZE 100
12
13 int main(void)
14 {
15     int sockfd;
16     struct sockaddr_in server;
17     struct sockaddr_in client;
18     socklen_t len;
19     int num;
20     char buf[MAXDATASIZE];
21     if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
22     {
23         perror("Creating socket failed.\n");
24         exit(1);
25     }
26     bzero(&server, sizeof(server));
27     server.sin_family = AF_INET;
28     server.sin_port = htons(PORT);
29     server.sin_addr.s_addr = htonl(INADDR_ANY);
30     if(bind(sockfd, (struct sockaddr *)&server, sizeof(server)) == -1)
31     {
32         perror("Bind() error.\n");
33         exit(1);
34     }
35
36     len = sizeof(client);
37     while(1)
38     {
39         num = recvfrom(sockfd, buf, MAXDATASIZE, 0, (struct sockaddr *)&client, &len);
40         if(num < 0)
41         {
42             perror("recvfrom() error.\n");
43             exit(1);
44         }
45         buf[num] = '\0';
46         printf("You got a message <%s> from client. \nIt's ip is %s, port is %d. \n", buf, inet_ntoa(client.sin_addr),htons(client.sin_port));
47         sendto(sockfd, "Welcome\n", 8, 0, (struct sockaddr *)&client, len);
48         if ( !strcmp(buf, "bye") ){
49             break;
50         }
51     }
52     close(sockfd);
53 }

2. 然后,我们给出带有connect的客户端程序:

UDPclientWithConnect.cpp

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <string.h>
 5 #include <sys/types.h>
 6 #include <sys/socket.h>
 7 #include <netinet/in.h>
 8 #include <netdb.h>
 9 #include <arpa/inet.h>
10
11 #define PORT 1234
12
13 #define MAXDATASIZE 100
14
15 int main(int argc, char *argv[])
16 {
17     int sockfd, num;
18     char buf[MAXDATASIZE];
19     struct hostent *he;
20     struct sockaddr_in server, peer;
21     if(argc != 3)
22     {
23         printf("Usage: %s <IP address> <message>\n", argv[0]);
24         exit(1);
25     }
26
27     if((sockfd=socket(AF_INET, SOCK_DGRAM, 0)) == -1)
28     {
29         printf("socket() error\n");
30         exit(1);
31     }
32     bzero(&server, sizeof(server));
33     server.sin_family = AF_INET;
34     server.sin_port = htons(PORT);
35
36     server.sin_addr.s_addr = inet_addr(argv[1]);
37     //server.sin_addr.s_addr = inet_addr(argv[1]);
38     if(connect(sockfd, (struct sockaddr *)&server, sizeof(server)) == -1)
39     {
40         printf("connect() error.\n");
41         exit(1);
42     }
43
44     send(sockfd, argv[2], strlen(argv[2]), 0);
45
46     while(1)
47     {
48         if((num = recv(sockfd, buf, MAXDATASIZE, 0)) == -1)
49         {
50             printf("recv() error.\n");
51             exit(1);
52         }
53
54         buf[num] = '\0';
55         printf("Server Message: %s.\n", buf);
56         break;
57     }
58     close(sockfd);
59 }

3. 最后,再给一个不带connect的客户端程序。

UDPclientNoConnect.cpp

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>#define PORT 1234#define MAXDATASIZE 100int main(int argc, char *argv[])
{int sockfd, num;char buf[MAXDATASIZE];struct hostent *he;struct sockaddr_in server, peer;if(argc != 3){printf("Usage: %s <IP address> <message>\n", argv[0]);exit(1);}if((he = gethostbyname(argv[1]))==NULL){printf("gethostbyname() error\n");exit(1);}if((sockfd=socket(AF_INET, SOCK_DGRAM, 0)) == -1){printf("socket() error\n");exit(1);}bzero(&server, sizeof(server));server.sin_family = AF_INET;server.sin_port = htons(PORT);server.sin_addr = *( (struct in_addr *)he->h_addr);sendto(sockfd, argv[2], strlen(argv[2]), 0, (struct sockaddr *)&server, sizeof(server));socklen_t len;len = sizeof(server);while(1){if((num = recvfrom(sockfd, buf, MAXDATASIZE, 0, (struct sockaddr *)&peer, &len)) == -1){printf("recvfrom() error\n");exit(1);}if(len != sizeof(server) || memcmp((const void *)&server, (const void *)&peer, len) != 0 ){printf("Receive message from other server.\n");continue;}buf[num] = '\0';printf("Server Message: %s.\n", buf);break;}close(sockfd);
}

执行一下命令进行编译:

$ g++ -o UDPserver UDPserver.cpp

$ g++ -o UDPclient2 UDPclientWithConnect.cpp

$ g++ -o UDPclient1 UDPclientNoConnect.cpp

完了以后就看到三个可执行文件了。

打开一个命令行,执行./UDPserver启动服务端程序,再打开另外一个命令行,执行./UDPclient1 127.0.0.1 "nihaonihao"或者./UDPclient2 127.0.0.1 "testtest"即可查看到以下效果:

[horstxu@vps ~/Cprog/udpCSmodel]$ ./UDPserver
You got a message <nihaonihao> from client.
It's ip is 127.0.0.1, port is 25595.
You got a message <testtest> from client.
It's ip is 127.0.0.1, port is 27396. 

[horstxu@vps ~/Cprog/udpCSmodel]$ ./UDPclient1 127.0.0.1 "nihaonihao"
Server Message: Welcome
.
[horstxu@vps ~/Cprog/udpCSmodel]$ ./UDPclient2 127.0.0.1 "testtest"
Server Message: Welcome
.
[horstxu@vps ~/Cprog/udpCSmodel]$ 

最后再来解释一个带有connect的UDP的好处。由于UDP是不可靠传输,如果我发了数据出去,对方其实服务器是关闭的,这时会有什么结果呢?对于刚才的UDPclient1,也就是不带connect的,客户端程序会卡在recvfrom这里,因为对方是关闭的,它永远也收不到来自对方的回包。但是对于UDPclient2,也就是带有connect,我们其实可以收到一个错误,并设置errno(errno:111,connection refused)。这样看上去就比卡死在那里友好多了。对于这个问题的具体分析可以参考这篇文章:

UDP怎么会返回Connection refused错误

[horstxu@vps ~/Cprog/udpCSmodel]$ ./UDPclient2 127.0.0.1 "testtest"
recv() error.
[horstxu@vps ~/Cprog/udpCSmodel]$ ./UDPclient1 127.0.0.1 "testtest" #注释:程序在这里卡死

转载于:https://www.cnblogs.com/xuning/p/4614458.html

[C语言]一个很实用的服务端和客户端进行UDP通信的实例相关推荐

  1. Winform中使用MQTTnet实现MQTT的服务端和客户端之间的通信以及将订阅的消息保存到文件

    场景 MQTT MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻 ...

  2. netcore 实现一个简单的Grpc 服务端和客户端

    参考资料,和详细背景不做赘述. 首先定义prop 文件 syntax ="proto3"; package RouteGrpc; service HelloWorld{ rpc S ...

  3. java贪吃蛇客户端服务器_java Socket套接字TCP编程开发服务端和客户端之间的通信 - 贪吃蛇学院-专业IT技术平台...

    超级简单,没有太多实质内容的Socket服务端,客户端小程序 先运行server 再运行client OK 服务端代码如下: public class Server { public static v ...

  4. 【Python 基础】网络编程 - Python写一个简单的HTTP服务端和客户端,实现Client/Server交互

    1.HTTP 首先讲一下http和https,详细可以去看runoob http-vs-https 基本概念 HTTP(HyperText Transfer Protocol:超文本传输协议)是一种用 ...

  5. 【计算机网络】服务端和客户端最大支持多少tcp连接?如何分析?

    文章目录 (一)引用文章 (二)简单分析: 1.基本概念:TCP四元组 2.多个客户端连接一个服务端最大支持最大多少tcp连接? 3.一个客户端连接一个服务端最大支持多少个tcp连接? (二)全面分析 ...

  6. Java中利用socket实现简单的服务端与客户端的通信(入门级)

    Java编程中,要想要使用网络通信,就离不开Socket编程,在此对socket进行简单的介绍.首先声明,这是一个入门级的介绍,仅仅简单的实现了客户端向服务端发送数据,服务端正常的接收数据,当接收到特 ...

  7. Java中Socket通信-服务端和客户端双向传输字符串实现

    场景 什么是socket 在计算机通信领域,socket 被翻译为"套接字",它是计算机之间进行通信的一种约定或一种方式.通过 socket 这种约定,一台计算机可以接收其他计算机 ...

  8. 服务端与客户端加密解密思路

    服务端与客户端加密解密思路 我的参考 我的理解 我的参考 源码编码 文档思路 我的理解 AES 对称加密,即加密解密使用共同的key AES是DES的升级版 RSA 非对称加密,即加密解密使用一对不同 ...

  9. SpringBoot(23) 集成socket.io服务端和客户端实现通信

    一.前言 websocket和socket.io区别? websocket 一种让客户端和服务器之间能进行双向实时通信的技术 使用时,虽然主流浏览器都已经支持,但仍然可能有不兼容的情况 适合用于cli ...

最新文章

  1. 关闭vmware喇叭报警声
  2. linux监控目录变动
  3. 机器学习实战读书笔记--决策树
  4. 《编译原理》实验报告——递归下降语法分析器的构建
  5. 基于友善之臂ARM-ContexA9-ADC驱动开发
  6. jQuery-动画排队
  7. 如何使用数据卷在宿主机和docker容器之间共享文件
  8. [基本功]假设检验概念统计量一览
  9. 前馈神经网络求解XOR问题
  10. Python爬虫是什么?
  11. PR剪辑-电子相册学习笔记
  12. 数字音频接口之TDM
  13. Django中filer和get的区别
  14. kali初讲——Metasploit工具MSF初学
  15. 苹果自带输入法怎么换行_Iphone手机原生输入法的5个技巧,学会了,才知道这么牛...
  16. 【Python学习】——读取HDF数据
  17. 人脸识别之人脸验证(五)--NormFace
  18. 解决电脑wlan被禁用无法再启动的办法.
  19. 新版Jsoncpp用法
  20. 获取页面离开onbeforeunload与onunload事件的返回值

热门文章

  1. [UE4]子控件Child Widget顶层容器选择
  2. u-boot.lds文件简介
  3. hdu 2196 树形dp
  4. 使用函数指针实现父类函数调用子类函数的两种方式
  5. C#委托及事件处理机制浅析
  6. uni-app 实现递增递减(js)
  7. IOS15打包动态库
  8. IOS之使用纯代码push ViewController
  9. 有监督学习和无监督学习举例_监督学习入门学习笔记
  10. 树莓派使用神经计算棒1代的准备(Tensorflow)