基于的UDP套件字编程流程
UDP传输层的协议,面向无连接,数据报的传输层协议。
“ 无连接 ”:不可靠
- 在网络环境较好的情况下,
UDP
效率较高 - 在网络环境较差的情况下,
UDP
可能存在丢包的情况 - 同时一些“ 实时应用 ” 采用
UDP
- 在应用层加一些保证传输可靠的“1
UCP
网络应用
Recver
接收端(TCP
)Sender
发送端(TCP
)
UDP网络应用的编程流程
UDP Sender(接收端)
:
创建一个套接字
同样使用socket
接口申请一个套接字
SOCK_DGRAM
类型的套接字
绑定网络地址
同样使用bind
接口将一个套接字和一个网络地址进行绑定
数据通信
接收
RECV(2) Linux Programmer's Manual RECV(2) NAME recv, recvfrom, recvmsg - receive a message from a socket SYNOPSIS #include <sys/types.h> #include <sys/socket.h> ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen); /* @描述: 从一个套接字中接收数据 @sockfd: 接收数据的套接字 @buf: 接收到的数据所存放的位置/空间 @len: 接收数据的空间有多大 @flags: 标志位: 一般为0 @src_addr: 指向网络地址信息的结构体空间,用来存储发送者信息的结构体,可以为 NULL,表示不关系发送者信息 @addrlen: 指向网络地址信息结构体的空间大小的指针 @return: 成功返回实际读取字节数 失败返回-1 */
关闭套接字
UDP Client(发送端)
:
创建一个套接字
同样使用socket接口申请一个套接字
SOCK_DGRAM
类型的套接字
数据通信
- 发送
SEND(2)
Linux Programmer's Manual
SEND(2)
NAME
send, sendto, sendmsg - send a message on a socket
SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *buf, size_t len, int
flags,const struct sockaddr *dest_addr, socklen_t addrlen);
/*
@描述:
通过一个合法套接字往一个指定的地址发送一条消息
@sockfd:
网络套接字
@buf:
需要发送的内容指针
@len:
需要发送的内容长度
@flags:
标志位:
一般采用0
@dest_addr:
目标地址,接收方的网络地址
@addrlen:
目标网络地址结构体的大小
@return:
成功返回实际发送的字节数
失败返回-1
*/
关闭套接字
示例
接收端
#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <cstring>
#include <arpa/inet.h>
#include <unistd.h>
using namespace std;
// UDP编程客户端
int main()
{
// 创建一个套接字
int socket_udpid = socket(AF_INET, SOCK_DGRAM, 0);
if(socket_udpid == -1)
{
perror("创建套接字失败");
return -1;
}
cout << " 套接字创建成功" << endl;
// 绑定一个网络地址:(bind)
struct sockaddr_in addr;// 指定为IPV4
addr.sin_family = AF_INET;
addr.sin_port = htons(8989); //指端口
addr.sin_addr.s_addr = inet_addr("192.168.5.128");
// sizeof(addr) 返回的值会被隐式转换为 socklen_t 类型。
if((bind(socket_udpid, (const struct sockaddr* )&addr, sizeof(addr))) == -1)
{
perror("绑定失败");
return -1;
}
cout << "绑定成功" << endl;
// 通信
while(1)
{
// 接收数据
char buf[1024] = {0};
struct sockaddr_in sendInfor;
socklen_t len = sizeof(sendInfor);
if(recvfrom(socket_udpid, buf, 1024 , 0 ,(struct sockaddr*) &sendInfor, &len) == -1)
{
perror("接收数据失败");
return -1;
}
if(strcmp(buf, "exit") == 0)
{
cout << "结束通信" << endl;
break;
}
cout << "接收到的数据是:" << buf << endl;
}
// 关闭套接字
close(socket_udpid);
return 0;
}
发送端
#include <winsock2.h>
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
// 初始化网络库
WSADATA wsData;
WSAStartup(MAKEWORD(2,2) ,&wsData);
// 创建套接字
SOCKET socket_udpid = socket(AF_INET, SOCK_DGRAM, 0);
if(socket_udpid == INVALID_SOCKET)
{
cerr << "连接失败,错误码:" << WSAGetLastError() << endl;
WSACleanup();
return -1;
}
// 设置接收端的地址
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8989);
addr.sin_addr.s_addr = inet_addr("192.168.5.128");
int addlen = sizeof(addr);
while(1)
{
//发送信息
char senfbuf[1024] = {0};
cout << "请输入";
cin >> senfbuf;
sendto(socket_udpid, senfbuf, sizeof(senfbuf), 0,(const sockaddr*)&addr, addlen );
if(strcmp(senfbuf, "exit") == 0)
{
cout << "结束通信" << endl;
break;
}
}
//关闭套接字
closesocket(socket_udpid);
return 0;
}