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;
}