温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

基于UDP的效劳器端和客户端

发布时间:2020-07-19 18:46:09 来源:网络 阅读:497 作者:yuw2017 栏目:网络安全

后面的文章中我们给出了几个TCP的例子,关于UDP而言,只需能了解后面的内容,完成并责难事。

UDP中的效劳器端和客户端没有衔接

UDP不像TCP,无需在衔接形态下交流数据,因而基于UDP的效劳器端和客户端也无需经由衔接进程。也就是说,不用挪用 listen() 和 accept() 函数。UDP中只要创立套接字的进程和数据交流的进程。

UDP效劳器端和客户端均只需1个套接字

TCP中,套接字是一对一的关系。如要向10个客户端供给效劳,那么除了担任监听的套接字外,还需求创立10套接字。但在UDP中,不论是效劳器端照样客户端都只需求1个套接字。之前说明UDP道理的时分举了邮寄包裹的例子,担任邮寄包裹的快递公司可以比方为UDP套接字,只需有1个快递公司,就可以经过它向恣意地址邮寄包裹。异样,只需1个UDP套接字就可以向恣意主机传送数据。

基于UDP的接纳和发送函数

创立好TCP套接字后,传输数据时无需再添加地址信息,由于TCP套接字将坚持与对方套接字的衔接。换言之,TCP套接字晓得目的地址信息。但UDP套接字不会坚持衔接形态,每次传输数据都要添加目的地址信息,这相当于在邮寄包裹前填写收件人地址。
发送数据运用 sendto() 函数:

			ssize_t sendto(int sock, void *buf, size_t nbytes, int flags, struct sockaddr *to, socklen_t addrlen); //Linux int sendto(SOCKET sock, const char *buf, int nbytes, int flags, const struct sockadr *to, int addrlen); //Windows

Linux和Windows下的 sendto() 函数相似,下面是具体参数阐明:

  • sock:用于传输UDP数据的套接字;

  • buf:保管待传输数据的缓冲区地址;

  • nbytes:带传输数据的长度(以字节计);

  • flags:可选项参数,若没有可传递0;

  • to:存有目的地址信息的 sockaddr 构造体变量的地址;

  • addrlen:传递给参数 to 的地址值构造体变量的长度。


UDP 发送函数 sendto() 与TCP发送函数 write()/send() 的最大差别在于,sendto() 函数需求向他传递目的地址信息。
接纳数据运用 recvfrom() 函数:

			ssize_t recvfrom(int sock, void *buf, size_t nbytes, int flags, struct sockadr *from, socklen_t *addrlen); //Linux int recvfrom(SOCKET sock, char *buf, int nbytes, int flags, const struct sockaddr *from, int *addrlen); //Windows

因为UDP数据的发送端不不定,所以 recvfrom() 函数界说为可接纳发送端信息的方式,详细参数如下:

  • sock:用于接纳UDP数据的套接字;

  • buf:保管接纳数据的缓冲区地址;

  • nbytes:可接纳的最大字节数(不克不及超越buf缓冲区的巨细);

  • flags:可选项参数,若没有可传递0;

  • from:存有发送端地址信息的sockaddr构造体变量的地址;

  • addrlen:保管参数 from 的构造体变量长度的变量地址值。

基于UDP的反响效劳器端/客户端

下面联合之前的内容完成反响客户端。需求留意的是,UDP分歧于TCP,不存在恳求衔接和受理进程,因而在某种意义上无法明白辨别效劳器端和客户端,只是由于其供给效劳而称为效劳器端,愿望列位读者不要曲解。
下面给出Windows下的代码,Linux与此相似,不再赘述。
效劳器端 server.cpp:

			#include <stdio.h> #include <winsock2.h> #pragma comment (lib, "ws2_32.lib") //加载 ws2_32.dll #define BUF_SIZE 100 int main(){ WSADATA wsaData; WSAStartup( MAKEWORD(2, 2), &wsaData); //创立套接字 SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); //绑定套接字 sockaddr_in servAddr; memset(&servAddr, 0, sizeof(servAddr)); //每一个字节都用0填充 servAddr.sin_family = PF_INET; //运用IPv4地址 servAddr.sin_addr.s_addr = htonl(INADDR_ANY); //主动获取IP地址 servAddr.sin_port = htons(1234); //端口 bind(sock, (SOCKADDR*)&servAddr, sizeof(SOCKADDR)); //接纳客户端恳求 SOCKADDR clntAddr; //客户端地址信息 int nSize = sizeof(SOCKADDR); char buffer[BUF_SIZE]; //缓冲区 while(1){ int strLen = recvfrom(sock, buffer, BUF_SIZE, 0, &clntAddr, &nSize); sendto(sock, buffer, strLen, 0, &clntAddr, nSize); } closesocket(sock); WSACleanup(); return 0; }

代码阐明:
1) 第12行代码在创立套接字时,向 socket() 第二个参数传递 SOCK_DGRAM,以指明运用UDP协定。
2) 第18行代码中运用htonl(INADDR_ANY)来主动获取IP地址。
应用常数 INADDR_ANY 主动获取IP地址有一个分明的益处,就是当软件装置到其他效劳器或许效劳器IP地址改动时,不必再更改源码从新编译,也不必在启动软件时手动输出。并且,假如一台盘算机中已分派多个IP地址(例如路由器),那么只需端标语分歧,就可以从分歧的IP地址接纳数据。所以,效劳器中优先思索运用INADDR_ANY;而客户端中除非带有一局部效劳器功用,不然不会采取。
客户端 client.cpp:

			#include <stdio.h> #include <WinSock2.h> #pragma comment(lib, "ws2_32.lib") //加载 ws2_32.dll #define BUF_SIZE 100 int main(){ //初始化DLL WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); //创立套接字 SOCKET sock = socket(PF_INET, SOCK_DGRAM, 0); //效劳器地址信息 sockaddr_in servAddr; memset(&servAddr, 0, sizeof(servAddr)); //每一个字节都用0填充 servAddr.sin_family = PF_INET; servAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); servAddr.sin_port = htons(1234); //不时获取用户输出并发送给效劳器,然后承受效劳器数据 sockaddr fromAddr; int addrLen = sizeof(fromAddr); while(1){ char buffer[BUF_SIZE] = {0}; printf("Input a string: "); gets(buffer); sendto(sock, buffer, strlen(buffer), 0, (struct sockaddr*)&servAddr, sizeof(servAddr)); int strLen = recvfrom(sock, buffer, BUF_SIZE, 0, &fromAddr, &addrLen); buffer[strLen] = 0; printf("Message form server: %s\n", buffer); } closesocket(sock); WSACleanup(); return 0; }

先运转 server,再运转 client,client 输入后果为:

Input a string: C言语中文网
Message form server: C言语中文网
Input a string: c.biancheng.net Founded in 2012
Message form server: c.biancheng.net Founded in 2012
Input a string:


从代码中可以看出,server.cpp 中没有运用 listen() 函数,client.cpp 中也没有运用 connect() 函数,由于 UDP 不需求衔接。


向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI