一、UDP
1.1 简介
UDP在传输过程中,不需要像TCP需要三次握手建立连接,从而提大幅提高通信间的效率,实时性强且开销小。但通信的稳定性和正确率却得不到保证;故被称为
无连接的不可靠报文传递
;
- 故在使用该协议进行传输时,为了保证数据的正确性,我们需要在应用层
添加辅助校验协议
来填补这个不足;
当然,UDP没有类似TCP的滑动窗口机制,故缓冲区被填满后,在接收数据即会出现丢包的现象;
- 使用服务器应用层设计流量控制,
控制发送数据速度
;- 在借助setsockopt函数
改变接收缓冲区大小
;
C/S模型
由于UDP不需要对客户端进行连接,只要客户端向指定的服务端发送数据即可,故可实现
并发
服务的能力;
1.2 常用函数‘
1.2.1 recvfrom
/**
* ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen)
* -------
* func:调用用于接收来自套接字的消息,并且可以用于接收套接字上的数据,不管它是否是面向连接的;
* param sockfd:文件描述符;
* param buf:存储集合;
* param len:存储集合长度;
* param flags:一般用0,阻塞接收;
* param src_addr:用来接收客户端地址、端口;
* param addrlen:结构体长度传出参数;
* return:返回接收字节数,失败返回-1,失联返回0;
* */
1.2.2 recv
/**
* ssize_t recv(int sockfd, void *buf, size_t len, int flags)
* -------
* func:通常只在一个连接的套接字上使用;
* param sockfd:文件描述符;
* param buf:存储集合;
* param len:存储集合长度;
* param flags:一般设置为0,阻塞接收;
* return:返回接收字节数,失败返回-1,失联返回0;
* */
1.2.3 send
/**
* ssize_t send(int sockfd, const void *buf, size_t len, int flags)
* -------
* func:只能在套接字处于连接状态时使用,发送数据;
* param sockfd:文件描述符;
* param buf:存储集合;
* param len:存储集合长度;
* param flags:一般设置为0,阻塞发送;
* return:返回发送字节数,失败返回-1;
* */
1.2.4 sendto
/**
* ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen)
* -------
* func:只能在套接字处于连接状态时使用,指定客户端发送数据;
* param sockfd:文件描述符;
* param buf:存储集合;
* param len:存储集合长度;
* param flags:一般设置为0,阻塞发送;
* param src_addr:传入客户端地址、端口;
* param addrlen:结构体长度;
* return:返回发送字节数,失败返回-1;
* */
server
/*----------------------------------------------------------------------
> File Name: UDPServer.cpp
> Author: Jxiepc
> Mail: Jxiepc
> Created Time: Mon 28 Feb 2022 10:34:52 AM CST
----------------------------------------------------------------------*/
#include <iostream>
#include <cstring>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <ctype.h>
#define MAXLEN 90
#define SERV_PORT 8888
void server() {
struct sockaddr_in serv_addr, clie_addr;
socklen_t clie_len;
int sfd;
char buf[MAXLEN], str[MAXLEN];
int i, n;
sfd = socket(AF_INET, SOCK_DGRAM, 0);
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(SERV_PORT);
bind(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
/* UDP与TCP的区别 */
while(1) {
/* 从客户端接收信息 */
clie_len = sizeof(clie_addr);
n = recvfrom(sfd, buf, MAXLEN, 0, (struct sockaddr*)&clie_addr, &clie_len);
if(n == -1) {
std::cout << "recvfrom error" << std::endl;
exit(-1);
}
for(i=0; i < n; ++i)
buf[i] = toupper(buf[i]);
/* 向客户端发送信息 */
n = sendto(sfd, buf, n, 0, (struct sockaddr*)&clie_addr, sizeof(clie_addr));
if(n == -1) {
std::cout << "sendto error" << std::endl;
exit(-1);
}
}
close(sfd);
}
int main(int argc, char* argv[])
{
server();
return 0;
}
client
/*----------------------------------------------------------------------
> File Name: UDPClie.cpp
> Author: Jxiepc
> Mail: Jxiepc
> Created Time: Mon 28 Feb 2022 11:11:13 AM CST
----------------------------------------------------------------------*/
#include <iostream>
#include <netinet/in.h>
#include <cstring>
#include <arpa/inet.h>
#include <sys/types.h>
#include <unistd.h>
#define SERV_PORT 8888
#define MAXLEN 80
void client() {
struct sockaddr_in serv_addr;
int sfd;
int n;
char buf[MAXLEN];
sfd = socket(AF_INET, SOCK_DGRAM, 0);
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr.s_addr);
while(fgets(buf, MAXLEN, stdin) != NULL) {
n = sendto(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
if(n == -1){
exit(-1);
}
n = recvfrom(sfd, buf, MAXLEN, 0, NULL, 0);
if(n == -1){
exit(-1);
}
std::cout << buf;
}
close(sfd);
}
int main(int argc, char* argv[])
{
client();
return 0;
}
二、组播
组播组可以是
永久
的也可以是临时
的;
- 组播组地址中,有一部分由
官方分配``的,称为永久组播组。永久组播组保持不变的是它的ip地址,组中的成员
构成`可变;- 永久组播组中成员的
数量
都可以是任意
的,甚至可以为零;- 那些没有保留下来供永久组播组使用的
ip组播地址
,可以被临时组播组利用。
224.0.0.0~224.0.0.255 为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其它地址供路由协议使用;
224.0.1.0~224.0.1.255 是公用组播地址,可以用于Internet;欲使用需申请。
224.0.2.0~238.255.255.255 为用户可用的组播地址(临时组地址),全网范围内有效;
239.0.0.0~239.255.255.255 为本地管理组播地址,仅在特定的本地范围内有效。