SDL_net TCP/UDP通信
SDL_net TCP/UDP通信
服务端:
- 初始化SDL_net库
- 设置监听的端口
- 打开一个socket绑定端口
- 接收连接
- 接受数据
- 对数据进行处理
- 清理,退出
单线程服务器示例:
#include <iostream>
#include<Windows.h>
#include<SDL.h>
#include<SDL_net.h>
#pragma comment(lib, "SDL2.lib")
#pragma comment(lib, "SDL2main.lib")
#pragma comment(lib, "SDL2_net.lib")
using namespace std;
int main(int argc, char* argv[])
{
TCPsocket sd, csd; //定义服务端socket,和接收客户端socket
IPaddress ip, * remoteIP; //定义本机IP,客户端IP
bool quit = false;
char buffer[512] = { 0 };//接收数据缓存
//初始化SDL_net库
if (SDLNet_Init() < 0)
{
cout << "SDLNet_Init error:" << SDLNet_GetError() << endl;
return -1;
}
//解析主机和端口,nullptr为本机默认,端口15366
if (SDLNet_ResolveHost(&ip, nullptr, 15366)) {
cout << "SDLNet_ResolveHost error:" << SDLNet_GetError() << endl;
return -1;
}
//得到的变量ip地址和端口号值是大端模式
//打开一个TCP socket网络,监听主机的端口
if (!(sd = SDLNet_TCP_Open(&ip)))
{
cout << "SDLNet_TCP_Open error:" << SDLNet_GetError() << endl;
return -1;
}
//等待连接,发送数据
while (true)
{
//检查sd是否有新的连接,如果有,就接受,打开一个新的socket
if ((csd = SDLNet_TCP_Accept(sd)))
{
//获取远程地址
if ((remoteIP = SDLNet_TCP_GetPeerAddress(csd)))
{
//输出地址,和端口
cout << "Host connected:" << SDLNet_Read32(&remoteIP->host);
cout << " " << SDLNet_Read16(&remoteIP->port) << endl;
char ip[32] = { 0 };
unsigned char* pch = (unsigned char*)&remoteIP->host;
sprintf_s(ip, "%d.%d.%d.%d", *pch, *(pch + 1), *(pch + 2), *(pch + 3));//将32位数字地址转为IP字符串形式
cout << ip << endl;
quit = false;
while (!quit)
{
int len = SDLNet_TCP_Recv(csd, buffer, 512);//这里是同步阻塞的
if (len > 0)//如果长度为0,则表示断开了连接
{
cout << buffer << endl;
if (strcmp(buffer, "exit") == 0)
{
quit = true;
}
}
else {
cout << "连接断开了" << endl;
break;
}
}
}
else {
cout << "SDLNet_TCP_GetPeerAddress error:" << SDLNet_GetError() << endl;
}
::SDLNet_TCP_Close(csd);//关闭连接
}
else {
SDL_Delay(100);//延时一下,不然等待连接的过程中,CPU占用高
}
}
SDLNet_TCP_Close(sd);//关闭服务端socket
SDLNet_Quit();//清理SDL_net库
return 0;
}
简易的多线程处理示例:
#include <iostream>
#include<Windows.h>
#include<SDL.h>
#include<SDL_net.h>
#include<thread>
#pragma comment(lib, "SDL2.lib")
#pragma comment(lib, "SDL2main.lib")
#pragma comment(lib, "SDL2_net.lib")
using namespace std;
/// <summary>
/// 处理客户端
/// </summary>
/// <param name="csd"></param>
void dohandle(TCPsocket csd)
{
IPaddress* remoteIP = nullptr;
string info = "";
//获取远程地址
if ((remoteIP = SDLNet_TCP_GetPeerAddress(csd)))
{
char ip[32] = { 0 };
unsigned char* pch = (unsigned char*)&remoteIP->host;
sprintf_s(ip, "%d.%d.%d.%d", *pch, *(pch + 1), *(pch + 2), *(pch + 3));//将32位数字地址转为IP字符串形式
info = string(ip) + ":" + to_string(remoteIP->port);
cout << "客户端:" << info << endl;
bool quit = false;
char buffer[512] = { 0 };
char send[512] = { 0 };
char serverN[] = "stdio回复:";
while (!quit)
{
memset(buffer, 0, sizeof(buffer));
int len = SDLNet_TCP_Recv(csd, buffer, sizeof(buffer));//这里是同步阻塞的
if (len > 0)//如果长度为0,则表示断开了连接
{
cout << "客户端(" << info << "):" << buffer << endl;
if (strcmp(buffer, "exit") == 0)//接收到字符"exit"则退出
{
quit = true;
}
else {
memset(send, 0, sizeof(send));
memcpy(send, serverN, sizeof(serverN));
strcat_s(send, buffer);
int l = SDLNet_TCP_Send(csd, send, strlen(send));//回复内容
}
}
else {//断开了
break;
}
}
}
else {
cout << "SDLNet_TCP_GetPeerAddress error:" << SDLNet_GetError() << endl;
}
cout << info << "断开了" << endl;
::SDLNet_TCP_Close(csd);//关闭连接
}
int main(int argc, char* argv[])
{
TCPsocket sd, csd; //定义服务端socket,和接收客户端socket
IPaddress ip, * remoteIP; //定义本机IP,客户端IP
bool quit = false;
char buffer[512] = { 0 };//接收数据缓存
//初始化SDL_net库
if (SDLNet_Init() < 0)
{
cout << "SDLNet_Init error:" << SDLNet_GetError() << endl;
return -1;
}
//解析主机和端口,nullptr为本机默认,端口15366
if (SDLNet_ResolveHost(&ip, nullptr, 15366)) {
cout << "SDLNet_ResolveHost error:" << SDLNet_GetError() << endl;
return -1;
}
//得到的变量ip地址和端口号值是大端模式
//打开一个TCP socket网络,监听主机的端口
if (!(sd = SDLNet_TCP_Open(&ip)))
{
cout << "SDLNet_TCP_Open error:" << SDLNet_GetError() << endl;
return -1;
}
//等待连接,发送数据
while (true)
{
//检查sd是否有新的连接,如果有,就接受,打开一个新的socket
if ((csd = SDLNet_TCP_Accept(sd)))
{
thread th(dohandle, csd);
th.detach();
}
else {
SDL_Delay(100);//延时一下,不然等待连接的过程中,CPU占用高
}
}
SDLNet_TCP_Close(sd);//关闭服务端socket
SDLNet_Quit();//清理SDL_net库
return 0;
}
客户端:
- 初始化SDL_net库
- 解析服务器地址
- 打开一个socket
- 读取数据
- 发送数据
- 清理,退出
简单示例:
#include <iostream>
#include<Windows.h>
#include<SDL.h>
#include<SDL_net.h>
#include<thread>
#pragma comment(lib, "SDL2.lib")
#pragma comment(lib, "SDL2main.lib")
#pragma comment(lib, "SDL2_net.lib")
using namespace std;
//接收数据处理线程
void dohandler(TCPsocket sd)
{
char buffer[512] = { 0 };
while (true)
{
memset(buffer, 0, 512);
int len = SDLNet_TCP_Recv(sd, buffer, 512);
if (len > 0)
{
cout << buffer << endl;
}
else
{
break;
}
}
}
int main(int argc, char* argv[])
{
IPaddress ip;
TCPsocket sd;
int quit, len;
char buffer[512] = { "hello" };
if (SDLNet_Init() < 0)//初始化
{
cout << "SDLNet_Init:" << SDLNet_GetError() << endl;
return -1;
}
const char* dstip = "127.0.0.1";//目标IP地址,这里测试使用本地
if (SDLNet_ResolveHost(&ip, dstip, 15366) < 0)//目标服务器端口号15366
{
cout << "SDLNet_ResolveHost:" << SDLNet_GetError() << endl;
return -1;
}
if (!(sd = SDLNet_TCP_Open(&ip)))//打开连接
{
cout << "SDLNet_TCP_Open:" << SDLNet_GetError() << endl;
return -1;
}
thread th(dohandler, sd);//线程处理
th.detach();
quit = 0;
while (!quit)
{
len = strlen(buffer) + 1;
if (SDLNet_TCP_Send(sd, buffer, len) < len)//发送数据
{
cout << "SDLNet_TCP_Send:" << SDLNet_GetError() << endl;
return -1;
}
SDL_Delay(1000);//延时1秒
}
SDLNet_TCP_Close(sd);
SDLNet_Quit();
return 0;
}
UDP部分
服务端:
- 初始化SDL_net库
- 在指定的端口打开一个socket
- 给数据包开辟内存
- 等待从客户端来的数据包
- 处理数据包
- 释放内存,退出
服务端示例:
#include <iostream>
#include<Windows.h>
#include<SDL.h>
#include<SDL_net.h>
#include<thread>
#pragma comment(lib, "SDL2.lib")
#pragma comment(lib, "SDL2main.lib")
#pragma comment(lib, "SDL2_net.lib")
using namespace std;
int main(int argc, char* argv[])
{
UDPsocket sd; //定义服务器socket
UDPpacket* p; //定义数据包
int quit;
//初始化SDL_net
if (SDLNet_Init() < 0)
{
cout << "SDLNet_Init:" << SDLNet_GetError() << endl;
return -1;
}
//打开一个socket端口15366
if (!(sd = SDLNet_UDP_Open(15366)))
{
cout << "SDLNet_UDP_Open:" << SDLNet_GetError() << endl;
return -1;
}
//给数据包开辟空间
if (!(p = SDLNet_AllocPacket(512)))
{
cout << "SDLNet_AllocPacket:" << SDLNet_GetError() << endl;
return -1;
}
quit = 0;
while (!quit)
{
if (SDLNet_UDP_Recv(sd, p))//接收数据
{
cout << "UDP Packet incoming" << endl;
cout << "Chan: " << p->channel << endl;
cout << "Data: " << p->data << endl;
cout << "Len: " << p->len << endl;
cout << "MaxLen: " << p->maxlen << endl;
cout << "Status: " << p->status << endl;
short port = SDLNet_Read16(&p->address.port);
unsigned char* ptr = (unsigned char*)&(p->address.host);
char buffer[20] = { 0 };
sprintf_s(buffer, "%d.%d.%d.%d", *ptr, *(ptr + 1), *(ptr + 2), *(ptr + 3));
cout << "Address:" << buffer << ":" << port << endl;
memset(p->data, 0, p->maxlen);//清空缓存区数据
}
}
SDLNet_UDP_Close(sd);
SDLNet_FreePacket(p);
SDLNet_Quit();
return 0;
}
客户端:
- 初始化SDL_net库
- 在一个随机的未使用的端口打开一个socket
- 解析服务器的地址
- 给数据包开辟内存
- 发送数据包
- 释放内存,退出
客户端示例:
#include <iostream>
#include<Windows.h>
#include<string>
#include<SDL.h>
#include<SDL_net.h>
#include<thread>
#pragma comment(lib, "SDL2.lib")
#pragma comment(lib, "SDL2main.lib")
#pragma comment(lib, "SDL2_net.lib")
using namespace std;
int main(int argc, char* argv[])
{
UDPsocket sd;
IPaddress srvadd;
UDPpacket* p;
int quit;
if (SDLNet_Init() < 0)
{
cout << "SDLNet_Init:" << SDLNet_GetError() << endl;
return -1;
}
//打开一个随机的端口
if (!(sd = SDLNet_UDP_Open(0)))
{
cout << "SDLNet_UDP_Open:" << SDLNet_GetError() << endl;
return -1;
}
if (SDLNet_ResolveHost(&srvadd, "127.0.0.1", 15366))
{
cout << "SDLNet_ResolveHost:" << SDLNet_GetError() << endl;
return -1;
}
if (!(p = SDLNet_AllocPacket(512)))
{
cout << "SDLNet_AllocPacket:" << SDLNet_GetError() << endl;
return -1;
}
quit = 0;
while (!quit)
{
time_t tt = time(nullptr);
char buffer[100] = { "hello" };
SDL_strlcat(buffer, to_string(tt).c_str(), 100);
memcpy_s(p->data, 512, buffer, 100);
p->address.host = srvadd.host;//设置主机地址
p->address.port = srvadd.port; //主机端口
p->len = strlen((char*)p->data) + 1;
int len = SDLNet_UDP_Send(sd, -1, p);//发送数据
memset(p->data, 0, p->maxlen);
SDL_Delay(1000);
}
SDLNet_FreePacket(p);
SDLNet_Quit();
return 0;
}