加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
udpclient.cpp 4.38 KB
一键复制 编辑 原始数据 按行查看 历史
Cverse 提交于 2023-03-07 10:42 . 添加项目文件。
#include "udpclient.h"
#include<qdebug.h>
#pragma pack(1)
UDPClient::UDPClient()
{
char ip[] = "47.113.197.15";
UDPClient(ip, 54321);
}
UDPClient::UDPClient(char* ip, int port) : srejoin(true),cport(pport)
{
//分配空间
rdata = new char[RBUF_SIZE];
sdata = new char[SBUF_SIZE];
rdata_ = new char[RBUF_SIZE];
sdata_ = new char[SBUF_SIZE];
//初始化
memset(rdata, 0, RBUF_SIZE);
memset(sdata, 0, SBUF_SIZE);
memset(rdata_, 0, RBUF_SIZE);
memset(sdata_, 0, SBUF_SIZE);
//初始化服务器的socket地址
sersin.sin_family = AF_INET;//协议版本
sersin.sin_addr.S_un.S_addr = inet_addr(ip);//服务器IP地址
sersin.sin_port = htons(port);//端口号0-65535
//初始化sinlen
sinlen = sizeof(SOCKADDR_IN);
//创建客户端与其他方交流的套接字
cli = CreateSocketUDP();
//talk to ser to get the sockaddr of peer
peer = TalkServer();
//绑定peer到cli也就是指定cli发收数据都是与peer
Connect();
}
UDPClient::~UDPClient()
{
//关闭socket
closesocket(cli);
qDebug() << "被释放拉woc";
//释放空间
delete[]rdata;
delete[]sdata;
delete[]rdata_;
delete[]sdata_;
}
SOCKADDR_IN UDPClient::TalkServer()
{
SOCKADDR_IN peersin;
//定期发送join/rejoin包给服务器,发送rejoin是防止原NAT映射被改变
memset(sdata, 0, SBUF_SIZE);
sdata[0] = 'j', sdata[1] = 'o', sdata[2] = 'i', sdata[3] = 'n';
SendToSer();
thread th1(&UDPClient::ReceSOCKADDR_IN,this);
memset(sdata, 0, SBUF_SIZE);
sdata[0] = 'r', sdata[1] = 'e', sdata[2] = 'j', sdata[3] = 'o';
while (srejoin) {
Sleep(3000);
SendToSer();
}
memcpy(&peersin, rdata, sinlen);
th1.join();
return peersin;
}
int UDPClient::Wsa()
{
//请求协议版本
WSADATA wsaData;
int err = WSAStartup(MAKEWORD(2, 2), &wsaData); //调用Winsock2.2版本
if (err != 0) printf("WSAStartup失败\n");
//检查版本是否正确
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
printf("请求协议版本失败\n");
return -1;
}
printf("请求协议版本成功\n");
return 0;
}
SOCKET UDPClient::CreateSocketUDP()
{
Wsa();
//创建socket
SOCKET clientSocket = socket(AF_INET, SOCK_DGRAM, 0);//第二个参数选择UDP/TCP
if (-1 == clientSocket)
{
printf("创建socket失败\n");
return -1;
}
printf("创建socket成功\n");
//设置本地socket地址信息
SOCKADDR_IN caddr = { 0 };
caddr.sin_family = AF_INET;//协议版本
caddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
caddr.sin_port = htons(pport);//端口号1024-65535
//绑定到socket
int r = ::bind(clientSocket, (sockaddr*)&caddr, sizeof(caddr));//绑定
//检查
if (-1 == r)
{
printf("bind失败\n");
WSACleanup();
return -1;
}
printf("bind成功\n");
return clientSocket; //返回创建的socket连接
}
void UDPClient::ReceSOCKADDR_IN()
{
memset(rdata, 0, RBUF_SIZE);
//读取server数据,有数据更新才读取,否则阻塞
recvfrom(cli, rdata, SBUF_SIZE, 0, NULL, 0);
srejoin = false;
}
void UDPClient::ReceData()
{
memset(rdata, 0, RBUF_SIZE);
//读取server数据,有数据更新才读取,否则阻塞
recvfrom(cli, rdata, SBUF_SIZE, 0, NULL, 0);
if (rdata[0] == 'x' && rdata[1] == 't') {
return;
}
else {
memset(rdata_, 0, RBUF_SIZE);
memcpy(rdata_, rdata, RBUF_SIZE);
}
}
point UDPClient::Rece()
{
point x;
memcpy(&x, rdata_, sizeof(point));
memset(rdata_, 0, RBUF_SIZE);
return x;
}
void UDPClient::Connect()
{
//连接另一台主机
int r = connect(cli, (sockaddr*)&peer, sizeof(peer));
if (-1 == r)
{
printf("连接主机失败\n");
return;
}
printf("连接主机成功\n");
}
void UDPClient::SendData()
{
memset(sdata, 0, SBUF_SIZE);
memcpy(sdata, sdata_, SBUF_SIZE);
memset(sdata_, 0, SBUF_SIZE);
if (sdata[0]=='0') { //无待发送的数据则发送心跳包防止路由断开
sdata[0] = 'x', sdata[1] = 't';
}
sendto(cli, sdata, SBUF_SIZE, 0, NULL, 0);
}
void UDPClient::Send(point x)
{
memset(sdata_, 0, SBUF_SIZE);
memcpy(sdata_, &x, sizeof(point));
}
void UDPClient::SendToSer()
{
sendto(cli, sdata, SBUF_SIZE, 0, (sockaddr*)&sersin, sinlen);
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化