不以物喜,不以己悲

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;
}
posted @ 2021-03-20 09:41  这种人  阅读(694)  评论(0编辑  收藏  举报