C++tcp服务器和跨平台客户端

TcpServer

#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <windows.h>
#include <winsock2.h>
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
#pragma comment(lib,"ws2_32.lib")

std::mutex g_Mutex;
bool g_IsQuit = false;

void QuitServer()
{
	while (!g_IsQuit)
	{
		short key = GetAsyncKeyState('A');
		if(key&0x0001)
		{
			g_Mutex.lock();
			g_IsQuit = true;
			g_Mutex.unlock();
		}
		std::this_thread::sleep_for(std::chrono::milliseconds(1));
	}
}

int main()
{
	//1.初始化网络环境
	WORD wVersion = MAKEWORD(2, 2);
	WSADATA wsaData;
	int err = WSAStartup(wVersion, &wsaData);

	if (err != 0)
	{
		printf("网络初始化错误,错误代码%d\n", err);
		system("pause");
		return 0;
	}

	//2.创建监听套接字
	SOCKET listenSock = socket(
		AF_INET,
		SOCK_STREAM,
		IPPROTO_TCP
	);
	if (INVALID_SOCKET == listenSock)
	{
		printf("监听套接字创建失败\n");
		WSACleanup();
		system("pause");
		return 0;
	}

	//3.设置服务器的端口信息
	sockaddr_in sin;
	sin.sin_port = htons(6666);
	sin.sin_family = AF_INET;
	sin.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//任意ip

	//4.绑定地址信息到监听套接字
	if (SOCKET_ERROR == bind(listenSock, (sockaddr*)&sin, sizeof(sin)))
	{
		printf("绑定监听套接字创建失败\n");
		closesocket(listenSock);
		WSACleanup();
		system("pause");
		return 0;
	}
	//5.开始监听
	if (SOCKET_ERROR == listen(listenSock, 100))
	{
		printf("监听出现错误\n");
		closesocket(listenSock);
		WSACleanup();
		system("pause");
		return 0;
	}

	//6.收发信息
	sockaddr_in clientaddinfo;
	int addlen = sizeof(clientaddinfo);
	SOCKET clientsock;

	clientsock = accept(listenSock, (sockaddr*)&clientaddinfo, &addlen);


	if (INVALID_SOCKET == clientsock)
	{
		printf("Accept错误\n");
		closesocket(listenSock);
		WSACleanup();
		system("pause");
		
		return 0;
	}

	//使用多线程转发和接收信息
	while (!g_IsQuit)
	{
		printf("接收到一个客户:%d,IP:%s,Port:&d\n",
			clientsock,
			inet_ntoa(clientaddinfo.sin_addr),
			clientaddinfo.sin_port);
		char buf[MAX_PATH] = {};
		recv(clientsock, buf, MAX_PATH - 1, 0);
		printf("接收到的数据:%s\n", buf);

		send(clientsock, "this is my backdata!", strlen("this is my backdata!") + 1,0);
	}

	//7.关闭套接字和网络环境
	closesocket(clientsock);
	closesocket(listenSock);
	WSACleanup();
	system("pause");
	return 0;
}

Linux跨平台网络客户端

#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <windows.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#else
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>

#define MAX_PATH	260
typedef int SOCKET;
#define INVALID_SOCKET (SOCKET)(~0)
#define SOCKET_ERROR			(-1)
#define WSACleanup() //

#endif
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
using namespace std;

bool g_IsQuit = false;
bool g_IsSend = false;
char g_SendBuffer[MAX_PATH];
mutex g_Mutex1;
mutex g_Mutex2;

void InputData()
{
	while (!g_IsQuit )
	{
		printf("input msg:\n");
		scanf("%s",g_SendBuffer);
		if (strcmp(g_SendBuffer,"exit")==0)
		{
			g_Mutex1.lock();
			g_IsQuit = true;
			g_Mutex1.unlock();
			break;
		}else if (!g_IsSend)
		{
			g_Mutex2.lock();
			g_IsSend = true;
			g_Mutex2.unlock();
		}
		this_thread::sleep_for(chrono::milliseconds(1));
	}
}



int main()
{
	#ifdef _WIN32
	WORD wVersion = MAKEWORD(2, 2);
	WSADATA wsaData;
	int err = WSAStartup(wVersion, &wsaData);
	if (err != 0)
	{
		printf("初始化错误%d\n", err);
		system("pause");
		return 0;
	}
	#endif

	SOCKET clientSock = socket(
		AF_INET,
		SOCK_STREAM,
		IPPROTO_TCP
		);

	if (INVALID_SOCKET == clientSock)
	{
		printf("create clientsocket failed\n");
		WSACleanup();
		system("pause");
		return 0;
	}

	sockaddr_in sin;
	sin.sin_port = htons(12345);
	sin.sin_family = AF_INET;
	#ifdef _WIN32
	sin.sin_addr.S_un.S_addr = inet_addr("192.168.1.2");
	#else 
	sin.sin_addr.s_addr = inet_addr("192.168.1.2");
	#endif

	if (SOCKET_ERROR == connect(clientSock, (sockaddr*)&sin, sizeof(sin)))
	{
		printf("错误\n");
		#ifdef _WIN32
		closesocket(clientSock);
		#else
		close(clientSock);
		#endif
		WSACleanup();
		system("pause");
		return 0;
	}

	thread inputthread(InputData);
	inputthread.detach();


	char recvdata[MAX_PATH] = {};
	while (!g_IsQuit)
	{
		if (g_IsSend)
		{
			printf("start send data\n");
			send(clientSock,g_SendBuffer, strlen(g_SendBuffer) + 1, 0);
			printf("start recv data\n");
			recv(clientSock, recvdata, MAX_PATH, 0);
			printf("reved msg:%s\n", recvdata);
			g_Mutex2.lock();
			g_IsSend = false;
			g_Mutex2.unlock();
			printf("lock end\n");
		}
		this_thread::sleep_for(chrono::milliseconds(1));
	}

	#ifdef _WIN32
	closesocket(clientSock);
	#else
	close(clientSock);
	#endif
	WSACleanup();
	return 0;
}

总结

  • 跨平台注意编码
  • 通过使用内置的宏,可以进行操作系统判断 #ifdef _WIN32 #endif
  • arpa/inet.h:IP地址转换
posted @ 2020-07-08 19:49  人閒桂花落  阅读(1001)  评论(0编辑  收藏  举报