TCP模式的一个服务器和多个客户端通信

 服务端

#define  _WINSOCK_DEPRECATED_NO_WARNINGS 
#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#pragma comment(lib,"ws2_32.lib")
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using std::string;
using std::map;
using std::vector;
map socketMap;

//发送数据
void WINAPI SendMsg()
{
	while (1)
	{
		//		'+' 43
		//		'/'	47
		//		'*' 42
		int key = _getch();
		if (key == 43)		//发送消息
		{
			printf("【*】群发【/】单发\n");
			key = _getch();
			printf("发送内容:");
			char sendStr[100] = {};
			gets_s(sendStr, sizeof(sendStr));
			//scanf("%s",sendStr);
			int sendRet = 0;

			if(key == 42 )	//群发
			{
				for (auto inter = socketMap.begin(); inter != socketMap.end(); ++inter)
				{
					SOCKET clientSocket = inter->second;
					sendRet = send(clientSocket, sendStr, strlen(sendStr), 0);
				}
			}
			else if(key == 47)		//单发
			{
				printf("客户端端口号:");
				int hostPort = 0;
				//scanf("%d",&port);
				char temp[100] = {};
				gets_s((char*)&temp, sizeof(temp));
				sscanf(temp, "%d", &hostPort);
				if (socketMap.find(hostPort) != socketMap.end())
				{
					SOCKET clientSocket = socketMap.at(hostPort);
					sendRet = send(clientSocket, sendStr, strlen(sendStr), 0);
				}
				else
				{
					printf("输入端口号有误\n");
					continue;
				}
			}

			if(sendRet != 0)
				printf("已发送\n");
			else
				printf("发送失败\n");
		}
	}
}

//接收客户端数据
DWORD WINAPI  RecvMsg(SOCKET* clientSocket)
{
	//int threadId = GetCurrentThreadId();
	//int n = 5;
	while (1)
	{
		char recvStr[10000] = {};
		int recvRet = recv(*clientSocket, recvStr, sizeof(recvStr), 0);
		if (recvRet != -1 && recvRet != 0)
			printf("thread【%d】:%s\n=========\n", (int)GetCurrentThreadId(), recvStr);
		else
		{
			auto retVal = std::find_if(socketMap.begin(), socketMap.end(), [clientSocket](map::value_type val)
			{
				return val.second == *clientSocket;
			});
			if (retVal != socketMap.end())
			{
				printf("客户端%d已断开\n", retVal->first);
				closesocket(retVal->second);
				socketMap.erase(retVal);
				break;
			}
			else
			{
				printf("没有该客户端\n");
			}
		}
	}
	return 0;
}

int main()
{	
	CreateThread(0, 0, (LPTHREAD_START_ROUTINE)SendMsg, 0, 0, 0);
	WSADATA wsaData = { 0 };
	WSAStartup(MAKEWORD(2,2),&wsaData);
	SOCKET serverSocket = socket(AF_INET,SOCK_STREAM,0);
	sockaddr_in sockaddr;
	sockaddr.sin_family = AF_INET;
	sockaddr.sin_addr.S_un.S_addr =  INADDR_ANY; 	//监听本机任意IP地址的8888端口
	//sockaddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	sockaddr.sin_port = htons(8888);
	int  bindRet = bind(serverSocket, (SOCKADDR*)&sockaddr, sizeof(sockaddr));
	if (bindRet == SOCKET_ERROR)
	{
		printf("绑定失败\n");
		closesocket(serverSocket);
		WSACleanup();
		getchar();
		exit(0);
	}
	int listenRet = listen(serverSocket, 3);  
	if (listenRet == -1)
	{
		printf("监听失败\n");
		closesocket(serverSocket);
		WSACleanup();
		system("pause");
		return 0;
	}
	printf("监听中...\n");
	

	while (1)
	{
		SOCKADDR_IN clientSockAddr_in = {};
		int len = sizeof(clientSockAddr_in);
		SOCKET clientSocket = accept(serverSocket, (SOCKADDR*)&clientSockAddr_in, &len);
		printf("有客户端连接\n");
		printf("ip=%s,port=%d\n", inet_ntoa(clientSockAddr_in.sin_addr), ntohs(clientSockAddr_in.sin_port));
		socketMap[ntohs(clientSockAddr_in.sin_port)] = clientSocket;
		CreateThread(0, 0, (LPTHREAD_START_ROUTINE)RecvMsg, &socketMap[ntohs(clientSockAddr_in.sin_port)], 0, 0);
	}
}

客户端

#define  _WINSOCK_DEPRECATED_NO_WARNINGS 
#define _CRT_SECURE_NO_WARNINGS

#include 
#include 
#pragma comment(lib,"ws2_32.lib")
#include 
#include 

DWORD WINAPI RecvMsg(const SOCKET* clientSocket)
{
	while (1)
	{
		char recvStr[100] = {};
		int recvRet = recv(*clientSocket, recvStr, sizeof(recvStr), 0);
		if (recvRet != -1)
			printf("服务器说:%s\n", recvStr);
		else
		{
			printf("服务器已断开\n");
			closesocket(*clientSocket);
			WSACleanup();
			system("pause");
			closesocket(*clientSocket);
			WSACleanup();
			exit(0);
		}
	}
	return 0;
}

int main()
{

	WSADATA wsaData = { 0 };
	WSAStartup(MAKEWORD(2, 2), &wsaData);
	SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, 0);
	//******bind自定义端口号测试*********/
	SOCKADDR_IN clientSockAddr_in = { 0 };
	clientSockAddr_in.sin_family = AF_INET;
	clientSockAddr_in.sin_addr.S_un.S_addr = INADDR_ANY;	//本机IP
	clientSockAddr_in.sin_port = htons(2222);
	if(bind(clientSocket, (SOCKADDR*)&clientSockAddr_in, sizeof(clientSockAddr_in)) == SOCKET_ERROR)
	{
		std::cout << "绑定套接字失败\n";
		closesocket(clientSocket);
		WSACleanup();
		system("pause");
		return 0;
	}
	/***************************************/

	SOCKADDR_IN sockaddr_in;
	sockaddr_in.sin_family = AF_INET;
	sockaddr_in.sin_addr.S_un.S_addr =  inet_addr("172.16.20.203");		//inet_addr("192.168.18.173");		//服务端ip地址
	//sockaddr_in.sin_addr.S_un.S_addr = inet_addr("192.168.74.128");
	sockaddr_in.sin_port = htons(8888);														//服务端监听的端口
	int conRet = connect(clientSocket,(SOCKADDR*)&sockaddr_in, sizeof(sockaddr_in));
	if (conRet != SOCKET_ERROR)
	{
		printf("连接成功\n");
		CreateThread(0, 0, (LPTHREAD_START_ROUTINE)RecvMsg, &clientSocket, 0, 0);
	}
		
	else
	{
		printf("连接失败,返回%d\n", conRet);
		closesocket(clientSocket);
		WSACleanup();
	}
		
	while (1)
	{
		printf("输入内容\n");
		char sendStr[10000] = {};
		//scanf("%s", sendStr);	//遇到空格会截断后面内容
		gets_s(sendStr, sizeof(sendStr));

		int ret = send(clientSocket, sendStr, strlen(sendStr), 0);
		if (ret != 0)
			printf("客户端发送数据%dbyte\n", ret);
	}
}

你可能感兴趣的:(计算机网络,tcp/ip,服务器,c语言)