zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Good Bye 2014 B. New Year Permutation(floyd )
    hdu 5147 Sequence II (树状数组 求逆序数)
    POJ 1696 Space Ant (极角排序)
    POJ 2398 Toy Storage (叉积判断点和线段的关系)
    hdu 2897 邂逅明下 (简单巴什博弈)
    poj 1410 Intersection (判断线段与矩形相交 判线段相交)
    HDU 3400 Line belt (三分嵌套)
    Codeforces Round #279 (Div. 2) C. Hacking Cypher (大数取余)
    Codeforces Round #179 (Div. 2) B. Yaroslav and Two Strings (容斥原理)
    hdu 1576 A/B (求逆元)
  • 原文地址:https://www.cnblogs.com/zzr-stdio/p/14559965.html
Copyright © 2011-2022 走看看