[C语言]一个很实用的服务端和客户端进行UDP通信的实例
前段时间发了个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通信的实例相关推荐
- Winform中使用MQTTnet实现MQTT的服务端和客户端之间的通信以及将订阅的消息保存到文件
场景 MQTT MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻 ...
- netcore 实现一个简单的Grpc 服务端和客户端
参考资料,和详细背景不做赘述. 首先定义prop 文件 syntax ="proto3"; package RouteGrpc; service HelloWorld{ rpc S ...
- java贪吃蛇客户端服务器_java Socket套接字TCP编程开发服务端和客户端之间的通信 - 贪吃蛇学院-专业IT技术平台...
超级简单,没有太多实质内容的Socket服务端,客户端小程序 先运行server 再运行client OK 服务端代码如下: public class Server { public static v ...
- 【Python 基础】网络编程 - Python写一个简单的HTTP服务端和客户端,实现Client/Server交互
1.HTTP 首先讲一下http和https,详细可以去看runoob http-vs-https 基本概念 HTTP(HyperText Transfer Protocol:超文本传输协议)是一种用 ...
- 【计算机网络】服务端和客户端最大支持多少tcp连接?如何分析?
文章目录 (一)引用文章 (二)简单分析: 1.基本概念:TCP四元组 2.多个客户端连接一个服务端最大支持最大多少tcp连接? 3.一个客户端连接一个服务端最大支持多少个tcp连接? (二)全面分析 ...
- Java中利用socket实现简单的服务端与客户端的通信(入门级)
Java编程中,要想要使用网络通信,就离不开Socket编程,在此对socket进行简单的介绍.首先声明,这是一个入门级的介绍,仅仅简单的实现了客户端向服务端发送数据,服务端正常的接收数据,当接收到特 ...
- Java中Socket通信-服务端和客户端双向传输字符串实现
场景 什么是socket 在计算机通信领域,socket 被翻译为"套接字",它是计算机之间进行通信的一种约定或一种方式.通过 socket 这种约定,一台计算机可以接收其他计算机 ...
- 服务端与客户端加密解密思路
服务端与客户端加密解密思路 我的参考 我的理解 我的参考 源码编码 文档思路 我的理解 AES 对称加密,即加密解密使用共同的key AES是DES的升级版 RSA 非对称加密,即加密解密使用一对不同 ...
- SpringBoot(23) 集成socket.io服务端和客户端实现通信
一.前言 websocket和socket.io区别? websocket 一种让客户端和服务器之间能进行双向实时通信的技术 使用时,虽然主流浏览器都已经支持,但仍然可能有不兼容的情况 适合用于cli ...
最新文章
- 关闭vmware喇叭报警声
- linux监控目录变动
- 机器学习实战读书笔记--决策树
- 《编译原理》实验报告——递归下降语法分析器的构建
- 基于友善之臂ARM-ContexA9-ADC驱动开发
- jQuery-动画排队
- 如何使用数据卷在宿主机和docker容器之间共享文件
- [基本功]假设检验概念统计量一览
- 前馈神经网络求解XOR问题
- Python爬虫是什么?
- PR剪辑-电子相册学习笔记
- 数字音频接口之TDM
- Django中filer和get的区别
- kali初讲——Metasploit工具MSF初学
- 苹果自带输入法怎么换行_Iphone手机原生输入法的5个技巧,学会了,才知道这么牛...
- 【Python学习】——读取HDF数据
- 人脸识别之人脸验证(五)--NormFace
- 解决电脑wlan被禁用无法再启动的办法.
- 新版Jsoncpp用法
- 获取页面离开onbeforeunload与onunload事件的返回值