UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议。这个通信协议主要有以下特点:
1.非面向连接通信
2.没有拥塞控制、重传机制
3.报文头8个Byte
4.适用与对数据实时性传输要求高的网络
IP地址+端口号+传输协议可以在网络中唯一的标记一个进程,UDP正是通过这个模式实现网络中客户端与服务端的配对通信。现在在windows环境下编写一个客户端发送数据到服务端的样例。其实无论是java还是C++网络编程,其基本原理都是一样的,甚至都是调用一些系统已经封装好的库函数。在windwos平台中我们将调用WSA(Windows Sockets Asynchronous)
主要用到两个”winsock2.h”中的函数
1.接收数据函数
int recvfrom(int sockfd,void *buf,int len,unsigned int lags,struct sockaddr *from,int *fromlen);
1.sockfd 定义的socket
2.buf 存储数据的缓冲区
3.len 缓冲区大小
4.lags 一般设置为0
5.from 保存源机的IP地址及端口号。
6.fromlen 当recvfrom()返回时,fromlen包含实际存入from中的数据字节数。
7.Recvfrom()函数返回接收到的字节数或当出现错误时返回-1,
2.发送数据函数
int sendto(int sockfd, const void *msg,int len unsigned int flags, const struct sockaddr *to, int tolen)
1.sockfd 定义的套接字
2.msg 存储要被发送的数据的缓冲区
3. len 缓冲区大小
4.flags 一般设为0
5. to 服务器地址
6. token 我们定义为服务的地址大小
服务端代码
#include<iostream>
#include <winsock2.h>
#include <windows.h>
#pragma comment(lib,"WS2_32.lib")
using namespace std;
int main() {
WSADATA data; //windows异步套接字数据结构体
WORD w = MAKEWORD(2, 0); //指定winsock 版本的为 2.0
WSAStartup(w, &data); //指定程序可以使用winsock 2.0版本的套接字
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0); //初始化套接字
sockaddr_in addr,addr2; //声明服务器地址和客户端地址
int token = sizeof(addr2); //以客户端地址的sizew为token
char buff[60] = { 0 }; //接收数据缓冲区
addr.sin_family = AF_INET; //使用IPv4协议簇
addr.sin_port = htons(71); //向71号端口发送数据
addr.sin_addr.S_un.S_addr = inet_addr("192.168.15.72"); //服务器本身地址
bind(s, (sockaddr*)&addr, sizeof(addr)); //将套接字和服务器地址绑定在一起
bool first = true; //第一次连接标记
cout << "服务器已经启动" << endl;
while (true)
{
if (recvfrom(s, buff, 60, 0, (sockaddr*)&addr2, &token) > 0) //从客户端接受数据
{
if (first)
{
cout<<"已经与客户端地址链接上: "<<inet_ntoa(addr2.sin_addr)<<endl;
first = false;
}
cout << buff << endl;//输出客户端内容
}
}
closesocket(s); //关闭套接字
WSACleanup(); //终止Ws2_32.dll的使用
}
WSADATA data; //这个结构被用来存储被WSAStartup函数调用后返回的Windows Sockets数据。它包含Winsock.dll执行的数据。
客户端代码
#include<iostream>
#include <winsock2.h>
#pragma comment(lib,"WS2_32.lib")
#include <windows.h>
#include<string>
using namespace std;
void UDPSendData(char* dataToSend,int len,string address)
{
WSADATA data;
WORD version = MAKEWORD(2, 0); //指定winsock 2.0套接字版本
WSAStartup(version, &data); //指定程序可以使用winsock 2.0版本的套接字
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0); //初始化套接字
const char *char_address = address.c_str(); //将传入的服务器地址从"string"转到"char *"
sockaddr_in server_addr; //声明服务器地址
int token = sizeof(server_addr); // 以sockeadr_in 的大小作为token
server_addr.sin_family = AF_INET; //使用IPv4协议簇
server_addr.sin_port = htons(71); //向71号端口发送数据
server_addr.sin_addr.S_un.S_addr = inet_addr(char_address);//发送到服务器的地址
sendto(s, dataToSend,len, 0, (sockaddr*)&server_addr, token); //发送数据到服务器
closesocket(s); //关闭套接字
WSACleanup(); //终止Ws2_32.dll的使用
}
int main() {
char *test = (char*)"Be the change you want to see in the world.";
string address = "192.168.15.72";
int len = strlen(test);
UDPSendData(test,len,address);
system("pause");
return 0;
}
运行验证
服务端
客户端
任何问题欢迎留言:)