SDL_net TCP/UDP通信

SDL_net TCP/UDP通信

服務端:

  1. 初始化SDL_net庫
  2. 設置監聽的端口
  3. 打開一個socket綁定端口
  4. 接收連接
  5. 接受數據
  6. 對數據進行處理
  7. 清理,退出

單線程服務器示例:

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

客戶端:

  1. 初始化SDL_net庫
  2. 解析服務器地址
  3. 打開一個socket
  4. 讀取數據
  5. 發送數據
  6. 清理,退出

簡單示例:

#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部分

服務端:

  1. 初始化SDL_net庫
  2. 在指定的端口打開一個socket
  3. 給數據包開闢內存
  4. 等待從客戶端來的數據包
  5. 處理數據包
  6. 釋放內存,退出

服務端示例:

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

客戶端:

  1. 初始化SDL_net庫
  2. 在一個隨機的未使用的端口打開一個socket
  3. 解析服務器的地址
  4. 給數據包開闢內存
  5. 發送數據包
  6. 釋放內存,退出

客戶端示例:

#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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章