一、简介
udp是面向报文的协议,它不保证消息的完整性,也不为消息提供超时或重发机制。但是,udp的优点是在性能方面比tcp好一些,因为它不建立连接,发送数据和接收数据都只需很少的资源。
二、UDP客户端
实现原理:该程序使用了C++的socket编程,通过UDP协议在本地和远程服务器之间进行通信。用户可以发送和接收消息。当用户输入'q'时,程序会退出聊天。
#include <Winsock2.h>
#include <iostream>
#include <stdio.h>
#pragma comment (lib, "ws2_32.lib")
int Start_T() {
//加载套接字库 必须不能省略
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1, 1);
err = WSAStartup(wVersionRequested, &wsaData);//错误会返回WSASYSNOTREADY
if (err != 0)
{
return 0;
}
if (LOBYTE(wsaData.wVersion) != 1 || //低字节为主版本
HIBYTE(wsaData.wVersion) != 1) //高字节为副版本
{
WSACleanup();
return 0;
}
printf("server is operating!\n\n");
//创建套接字
SOCKET sockfd = socket(AF_INET, SOCK_DGRAM, 0);
//定义一个ipv4存放本地信息
SOCKADDR_IN myaddr = { 0 };
myaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(5210);
//定义一个ipv4地址结构存放服务器地址信息
SOCKADDR_IN ser_addr = { 0 };
ser_addr.sin_addr.S_un.S_addr = inet_addr("192.168.99.101");
ser_addr.sin_family = AF_INET;
ser_addr.sin_port = htons(5210);
//绑定
bind(sockfd, (SOCKADDR*)&myaddr, sizeof(SOCKADDR));
int len = sizeof(SOCKADDR);
char recvBuf[100]; //收
char sendBuf[100]; //发
char tempBuf[100]; //存储中间信息数据
while (1) {
//发送
std::cout << "im client Please input data:" << std::endl;
std::cin >> sendBuf;
if ('q' == sendBuf[0])
{
sendto(sockfd, "q", strlen("q") + 1, 0, (SOCKADDR*)&ser_addr, len);
std::cout << "Chat end!";
break;
}
sendto(sockfd, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&ser_addr, len);
//接收
std::cout << "wait to received" << std::endl;
int len = recvfrom(sockfd, recvBuf, sizeof(recvBuf), 0, NULL, NULL);
if ('q' == recvBuf[0])
{
sendto(sockfd, "q", strlen("q") + 1, 0, (SOCKADDR*)&ser_addr, len);
std::cout << "Chat end!";
break;
}
std::cout << recvBuf << std::endl;
}
//关闭
closesocket(sockfd);
WSACleanup();
return 0;
}
三、UDP服务器
这段C++代码实现了一个简单的聊天服务器程序。它的用途是接收客户端的输入,并将其发送回客户端。当客户端输入 'q' 时,聊天服务器结束运行。
实现原理如下:
- 包含必要的头文件,如Windows socket库、iostream和stdio。
- 定义一个
Start_T
函数,用于初始化Windows socket库并创建一个UDP socket。 - 创建一个
SOCKADDR_IN
结构体变量myaddr
,用于存储本地IP地址和端口。 - 使用
socket
函数创建一个socket,并使用bind
函数绑定到本地地址和端口。 - 定义一些变量用于接收和发送数据,如
recvBuf
、sendBuf
和tempBuf
。 - 使用
recvfrom
函数接收客户端的数据,并将其存储在recvBuf
中。 - 如果接收到 'q',则发送 'q' 回客户端,并退出循环。
- 使用
sendto
函数将数据发送回客户端。 - 当客户端发送 'q' 时,聊天服务器结束运行。
- 关闭socket并释放资源。
#include <Winsock2.h>
#include <iostream>
#include <stdio.h>
#pragma comment (lib, "ws2_32.lib")
int Start_T() {
//加载套接字库 必须不能省略
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1, 1);
err = WSAStartup(wVersionRequested, &wsaData);//错误会返回WSASYSNOTREADY
if (err != 0)
{
return 0;
}
if (LOBYTE(wsaData.wVersion) != 1 || //低字节为主版本
HIBYTE(wsaData.wVersion) != 1) //高字节为副版本
{
WSACleanup();
return 0;
}
printf("server is operating!\n\n");
//创建套接字
SOCKET sockfd = socket(AF_INET, SOCK_DGRAM, 0);
//定义一个ipv4存放本地信息
SOCKADDR_IN myaddr = { 0 };
myaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(5210);
//绑定
bind(sockfd, (SOCKADDR*)&myaddr, sizeof(SOCKADDR));
int len = sizeof(SOCKADDR);
char recvBuf[100] = { 0 }; //收
char sendBuf[100] = { 0 }; //发
char tempBuf[100] = { 0 }; //存储中间信息数据
//来自的地址信息
SOCKADDR_IN from_addr = { 0 };
int from_len = sizeof(from_addr);
while (1) {
//接收
std::cout << "wait to received" << std::endl;
int len = recvfrom(sockfd, recvBuf, sizeof(recvBuf), 0, (SOCKADDR*)&from_addr, &from_len);
if ('q' == recvBuf[0])
{
sendto(sockfd, "q", strlen("q") + 1, 0, (SOCKADDR*)&from_addr, from_len);
std::cout << "Chat end!";
break;
}
std::cout << recvBuf << std::endl;
//发送
std::cout << "im Server Please input data:" << std::endl;
std::cin >> sendBuf;
if ('q' == sendBuf[0])
{
sendto(sockfd, "q", strlen("q") + 1, 0, (SOCKADDR*)&from_addr, from_len);
std::cout << "Chat end!";
break;
}
sendto(sockfd, sendBuf, strlen(sendBuf) + 1, 0, (SOCKADDR*)&from_addr, from_len);
}
closesocket(sockfd);
WSACleanup();
}