创建网络服务器和客户端

TCP服务端

// 01_TCP服务端.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#define _WINSOCK_DEPRECATED_NO_WARNINGS 

#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
#include<windows.h>
#include<stdio.h>

// 1. 初始化套接字环境       WSAStartup
// 2. 创建套接字             socket
// 3. 绑定套接字             bind
// 4. 监听套接字             listen
// 5. 等待连接               accept
// 6. 收发数据               send/recv
// 7. 关闭套接字             closesocekt
// 8. 清空环境               WSACleanup

int main()
{
	WSADATA data;
	// 1. 初始化套接字环境       WSAStartup
	if (WSAStartup(
		MAKEWORD(2, 2),		// 请求加载版本
		&data) != 0		  // 实际加载版本
		)
	{
		printf("初始化环境失败\n");
		return 0;
	}
	// 2. 创建套接字             socket
	SOCKET ServerSock = socket(
		AF_INET,		//通讯协议
		SOCK_STREAM,	//套接字类型
		IPPROTO_TCP	//传输协议
	);
	if (ServerSock == INVALID_SOCKET)
	{
		printf("创建套接字失败\n");
		return 0;
	}

	SOCKADDR_IN ServerSockaddr = {};
	int socklen = sizeof(sockaddr);		// 地址大小
	ServerSockaddr.sin_family = AF_INET;		// 网络协议
	ServerSockaddr.sin_port = htons(1234);	// 网络端口,需要转换网络字节序
	ServerSockaddr.sin_addr.S_un.S_addr =			// 网络IP地址
		inet_addr("127.0.0.1");	
	// 127.0.0.1 本地回环地址,用于做测试,同一台电脑

	// 3. 绑定套接字             bind
	if (SOCKET_ERROR == bind(
		ServerSock,						// 套接字
		(SOCKADDR*)&ServerSockaddr,		// 地址信息
		socklen)						// 地址长度
		)
	{
		printf("绑定套接字失败\n");
		return 0;
	}

	// 4. 监听套接字             listen
	printf("正在监听。。。。\n");
	listen(
		ServerSock,			// 套接字
		SOMAXCONN);			// 允许连接最大数量

	SOCKADDR_IN ClinetAddress = {}; //客户端地址
	SOCKET ClinetSock = NULL;		//客户端套接字
	socklen = sizeof(SOCKADDR_IN);

	// 5. 等待连接               accept
	ClinetSock = accept(
		ServerSock,					//	套接字
		(SOCKADDR*)&ClinetAddress,	//	客户地址
		&socklen);					//  地址长度-必须填写值
	if (ClinetSock == INVALID_SOCKET)
	{
		printf("等待客户连接失败\n");
		return 0;
	}
	char msg[100] = { "hello clinet" };
	// 6. 收发数据               send/recv
	printf("数据发送中....\n");
	send(
		ClinetSock,			//	客户套接字
		msg,				//  发送的消息
		13,					//  消息长度
		0);					//  发送标志,默认0
	// 收消息
	recv(
		ClinetSock,			//	客户套接字
		msg,				//  接受的缓冲区
		1024,				//  缓冲区大小
		0);					//  接受标志,默认0
	printf("接收到客户数据:%s\n",msg);

// 7. 关闭套接字             closesocket
	closesocket(ClinetSock);
	closesocket(ServerSock);
	
// 8. 清空环境               WSACleanup
	WSACleanup();

	getchar();
	return 0;
}


TCP客户端

// 02_TCP客户端.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#define _WINSOCK_DEPRECATED_NO_WARNINGS 

#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
#include<windows.h>
#include<stdio.h>

// 1. 初始化套接字环境       WSAStartup
// 2. 创建套接字             socket
// 3. 绑定套接字             bind     可以没有,系统自动分配

// 4. 发起连接               connect
// 5. 收发数据               send/recv
// 6. 关闭套接字             closesocekt
// 7. 清空环境               WSACleanup



int main()
{
	WSADATA data;
	// 1. 初始化套接字环境       WSAStartup
	if (WSAStartup(
		MAKEWORD(2, 2),		// 请求加载版本
		&data) != 0		  // 实际加载版本
		)
	{
		printf("初始化环境失败\n");
		return 0;
	}
	// 2. 创建套接字             socket
	SOCKET ClinetSock = socket(
		AF_INET,		//通讯协议
		SOCK_STREAM,	//套接字类型
		IPPROTO_TCP		//传输协议
	);

	if (ClinetSock == INVALID_SOCKET)
	{
		printf("创建套接字失败\n");
		return 0;
	}
	SOCKADDR_IN ServerSockAddr = {};			// 服务端地址信息
	int socklen = sizeof(sockaddr);				// 地址大小
	ServerSockAddr.sin_family = AF_INET;		// 网络协议
	ServerSockAddr.sin_port = htons(1234);		// 服务端的网络端口
	ServerSockAddr.sin_addr.S_un.S_addr =	    // 服务端的IP地址
		inet_addr("127.0.0.1");

	// 4. 发起连接               connect
	if (SOCKET_ERROR == connect(
		ClinetSock,						//客户端套接字
		(SOCKADDR*)&ServerSockAddr,		//服务端地址信息
		sizeof(SOCKADDR)				//地址长度
	))
	{
		printf("连接服务端失败\n");
		return 0;
	}

	printf("等待数据...\n");
	char buff[1024] = {};
	// 5. 收发数据               send/recv
	recv(						// recv接受成功返回数据长度
		ClinetSock,
		buff,
		1024,
		0);
	printf("收到来自服务端消息:%s\n", buff);

	// 发送数据给服务端
	send(
		ClinetSock,
		"hello server",
		13,
		0);
	

	// 7. 关闭套接字             closesocket
	closesocket(ClinetSock);

	// 8. 清空环境               WSACleanup
	WSACleanup();

	getchar();
	return 0;

}


UDP服务器

// 03_UDP服务器.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>

#define _WINSOCK_DEPRECATED_NO_WARNINGS 

#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
#include<windows.h>
#include<stdio.h>

// 1. 初始化套接字环境       WSAStartup
// 2. 创建套接字             socket
// 3. 绑定套接字             bind
// 4. 等待数据               recvfrom
// 5. 发送数据               sendto
// 6. 关闭套接字             closesocekt
// 7. 清空环境               WSACleanup
// 线程函数2

// 被作为线程回调函数参数的结构体
typedef struct _THREAD_PARAM
{
	SOCKET m_ServerSock;
	char*  m_buff;
	SOCKADDR_IN m_ClientAddress;
	int m_AddrLen;
} THREAD_PARAM, * PTHREAD_PARAM1;


DWORD WINAPI WorkerThreadB(LPVOID lpThreadParameter)
{
	// 通过强转获取到创建线程时传入的参数
	PTHREAD_PARAM1 ParamPoint = (PTHREAD_PARAM1)lpThreadParameter;
	while (true)
	{
		printf("等待数据......\n");
		recvfrom(
			ParamPoint->m_ServerSock,						// 套接字句柄
			ParamPoint->m_buff,							// 接受数据缓冲区
			1024,							// 缓冲区大小
			0,								// 标志
			(SOCKADDR*)&ParamPoint->m_ClientAddress,		// 接受数据时客户端地址信息
			&ParamPoint->m_AddrLen);						// 地址信息长度 -必须填充数据
		printf("来自客户端数据:%s......\n", ParamPoint->m_buff);
	}
	return 0;
}

int main()
{
	// 通常给线程提供的参数都会被放在堆空间中,防止函数退出时自动销毁
	PTHREAD_PARAM1 ParamPoint = new THREAD_PARAM{};
	WSADATA data;
	// 1. 初始化套接字环境       WSAStartup
	if (WSAStartup(
		MAKEWORD(2, 2),		// 请求加载版本
		&data) != 0		  // 实际加载版本
		)
	{
		printf("初始化环境失败\n");
		return 0;
	}
	// 2. 创建套接字             socket
	SOCKET ServerSock = socket(
		AF_INET,		//通讯协议
		SOCK_DGRAM,		//套接字类型
		IPPROTO_UDP		//传输协议
	);
	if (ServerSock == INVALID_SOCKET)
	{
		printf("创建套接字失败\n");
		return 0;
	}
	
	SOCKADDR_IN ServerSockaddr = {};
	int socklen = sizeof(sockaddr);			// 地址大小
	ServerSockaddr.sin_family = AF_INET;	// 网络协议
	ServerSockaddr.sin_port = htons(1234);	// 网络端口,需要转换网络字节序
	ServerSockaddr.sin_addr.S_un.S_addr =	// 网络IP地址
		inet_addr("127.0.0.1");
	// 127.0.0.1 本地回环地址,用于做测试,同一台电脑

	// 3. 绑定套接字             bind
	if (SOCKET_ERROR == bind(
		ServerSock,						// 套接字
		(SOCKADDR*)&ServerSockaddr,		// 地址信息
		socklen)						// 地址长度
		)
	{
		printf("绑定套接字失败\n");
		return 0;
	}

	char buff[1024] = {};
	SOCKADDR_IN ClientAddress = {};
	int AddrLen = sizeof(SOCKADDR_IN);

	
	// 4. 等待数据               recvfrom
	ParamPoint->m_AddrLen = AddrLen;
	ParamPoint->m_buff = buff;
	ParamPoint->m_ClientAddress = ClientAddress;
	ParamPoint->m_ServerSock = ServerSock;
	//创建线程
	HANDLE hThread2 = CreateThread(NULL, NULL, WorkerThreadB, ParamPoint, NULL, NULL);
	

	printf("正在发送数据......\n");
	// 5. 发送数据               sendto
	sendto(
		ServerSock,						//套接字句柄
		"hello udp client\n",			// 待发送的数据
		18,								// 待发送的数据长度
		0,								// 标志
		(SOCKADDR*)&ClientAddress,		// 给客户端发送数据
		sizeof(SOCKADDR)				// 地址长度
	);

	WaitForSingleObject(hThread2, -1);
	// 6. 关闭套接字             closesocket
	closesocket(ServerSock);

	// 8. 清空环境               WSACleanup
	WSACleanup();

	getchar();
	return 0;

}

UDP 客户端

// 04_UDP客户端.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//


#define _WINSOCK_DEPRECATED_NO_WARNINGS 

#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
#include<windows.h>
#include<stdio.h>

// 1. 初始化套接字环境       WSAStartup
// 2. 创建套接字             socket
// 3. 发送数据               sendto
// 4. 等待数据               recvfrom
// 5. 关闭套接字             closesocekt
// 7. 清空环境               WSACleanup


int main()
{
	WSADATA data;
	// 1. 初始化套接字环境       WSAStartup
	if (WSAStartup(
		MAKEWORD(2, 2),		// 请求加载版本
		&data) != 0		  // 实际加载版本
		)
	{
		printf("初始化环境失败\n");
		return 0;
	}
	// 2. 创建套接字             socket
	SOCKET ServerSock = socket(
		AF_INET,		//通讯协议
		SOCK_DGRAM,		//套接字类型
		IPPROTO_UDP		//传输协议
	);
	if (ServerSock == INVALID_SOCKET)
	{
		printf("创建套接字失败\n");
		return 0;
	}

	SOCKADDR_IN ServerSockaddr = {};
	int socklen = sizeof(sockaddr);			// 地址大小
	ServerSockaddr.sin_family = AF_INET;	// 网络协议
	ServerSockaddr.sin_port = htons(1234);	// 网络端口,需要转换网络字节序
	ServerSockaddr.sin_addr.S_un.S_addr =	// 网络IP地址
		inet_addr("127.0.0.1");
	// 127.0.0.1 本地回环地址,用于做测试,同一台电脑

	printf("正在发送数据...\n");
	// 4. 发送数据               sendto
	sendto(
		ServerSock,						//套接字句柄
		"hello udp server\n",			// 待发送的数据
		18,								// 待发送的数据长度
		0,								// 标志
		(SOCKADDR*)&ServerSockaddr,		// 给服务端发送数据
		sizeof(SOCKADDR)				// 地址长度
	);
	char buff[1024] = {};
	printf("等待接受数据...\n");
	// 4. 等待数据               recvfrom
	recvfrom(
		ServerSock,						// 套接字句柄
		buff,							// 接受数据缓冲区
		1024,							// 缓冲区大小
		0,								// 标志
		(SOCKADDR*)&ServerSockaddr,		// 接受数据时客户端地址信息
		&socklen);						// 地址信息长度 -必须填充数据

	printf("接受到服务端数据:%s\n", buff);

	// 6. 关闭套接字             closesocket
	closesocket(ServerSock);

	// 8. 清空环境               WSACleanup
	WSACleanup();

	getchar();
	return 0;

}


IOCP客户端

// 05_完成端口.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#define _WINSOCK_DEPRECATED_NO_WARNINGS 

#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
#include<windows.h>
#include<stdio.h>

// C++的继承,
struct MYOVERLAPPED :
	OVERLAPPED
{
public:
	WSABUF m_buff ;				// 消息缓冲区
	SOCKET m_ClinetSock;		// 客户端套接字
	SOCKADDR_IN m_ClientAddr;   // 客户地址信息

	// 调用构造函数
	MYOVERLAPPED(SOCKET sock, SOCKADDR_IN addr)
		:OVERLAPPED()			//调用父类构造,初始化0
	{
		m_buff.buf = new char[1024]{};
		m_buff.len = 1024;
		m_ClinetSock = sock;
		m_ClientAddr = addr;
	}

	~MYOVERLAPPED()
	{
		delete[]m_buff.buf;
		m_buff.buf = NULL;
		closesocket(m_ClinetSock);
	}


};


// 1. 初始化套接字环境
// 2. 创建套接字
// 3. 绑定套接字
// 4. 监听套接字
// 5. 创建一个完成端口 - 指定线程数 CPU核心数*2
// 6. 创建工作线程 - CPU核心数*2
//      6.1 等待完成端口 GetQueuedCompletionStatus
//      6.2 处理消息

// 7. 等待连接
// 8. 将客户套接字与完成端口进行绑定
// 9. 发起一个异步读IO请求



// 工作线程
DWORD WINAPI WorkThread(LPVOID param)
{
	// 获取完成端口
	HANDLE hIoCompletionProt = (HANDLE)param;
	DWORD dwSize = 0;
	DWORD dwCompletionKey = 0;
	MYOVERLAPPED* pov = NULL;
	BOOL bret = TRUE;

	//  6.1 等待完成端口 GetQueuedCompletionStatus
	while (TRUE)
	{
		bret = GetQueuedCompletionStatus(
			hIoCompletionProt,				// 完成端口句柄
			&dwSize,						// 实际完成大小
			&dwCompletionKey,				// 完成键
			(OVERLAPPED**)&pov,				// 重叠IO结构体
			-1								// 等待时间
		);
	
		if (bret != FALSE && pov != NULL)
		{
			//      6.2 处理消息
			// 接受数据失败,对方断开网络
			if (pov->InternalHigh == 0 || pov->InternalHigh == -1)
			{
				// 删除重叠IO结构体
				delete pov;
			}
			else {
				// 接受数据
				printf("接受到 %s:%d :%s\n",
					inet_ntoa(pov->m_ClientAddr.sin_addr),	// 客户端IP信息
					ntohs(pov->m_ClientAddr.sin_port),		// 客户端端口
					pov->m_buff.buf);

				// 继续投递异步读IO消息
				DWORD dwReadSize = 0;
				DWORD dwFlags = 0;

				WSARecv(
					pov->m_ClinetSock,		// 接受数据套接字
					&pov->m_buff,			// 缓冲区结构体
					1,						// 缓冲区个数
					&dwReadSize,			// 实际字节数
					&dwFlags,				// 标志
					pov,					// 重叠IO
					NULL					// 完成时调用函数
				);

			}
		}


	}
	return 0;
}


int main()
{
	WSADATA data;
	// 1. 初始化套接字环境       WSAStartup
	if (WSAStartup(
		MAKEWORD(2, 2),		// 请求加载版本
		&data) != 0		  // 实际加载版本
		)
	{
		printf("初始化环境失败\n");
		return 0;
	}
	// 2. 创建套接字             socket
	SOCKET ServerSock = socket(
		AF_INET,		//通讯协议
		SOCK_STREAM,	//套接字类型
		IPPROTO_TCP	//传输协议
	);
	if (ServerSock == INVALID_SOCKET)
	{
		printf("创建套接字失败\n");
		return 0;
	}

	SOCKADDR_IN ServerSockaddr = {};
	int socklen = sizeof(sockaddr);		// 地址大小
	ServerSockaddr.sin_family = AF_INET;		// 网络协议
	ServerSockaddr.sin_port = htons(1234);	// 网络端口,需要转换网络字节序
	ServerSockaddr.sin_addr.S_un.S_addr =			// 网络IP地址
		inet_addr("127.0.0.1");
	// 127.0.0.1 本地回环地址,用于做测试,同一台电脑

	// 3. 绑定套接字             bind
	if (SOCKET_ERROR == bind(
		ServerSock,						// 套接字
		(SOCKADDR*)&ServerSockaddr,		// 地址信息
		socklen)						// 地址长度
		)
	{
		printf("绑定套接字失败\n");
		return 0;
	}

	// 4. 监听套接字             listen
	printf("正在监听。。。。\n");
	listen(
		ServerSock,			// 套接字
		SOMAXCONN);			// 允许连接最大数量

	SOCKADDR_IN ClinetAddress = {}; //客户端地址
	SOCKET ClinetSock = NULL;		//客户端套接字
	socklen = sizeof(SOCKADDR_IN);

	// 5. 创建一个完成端口 - 指定线程数 CPU核心数*2
	SYSTEM_INFO info;
	HANDLE hIoCompletionProt = NULL;
	GetSystemInfo(&info);					// 获取系统信息
	hIoCompletionProt =
		CreateIoCompletionPort(					// 创建完成端口
			INVALID_HANDLE_VALUE,				// 如果第一个参数是-1,说明要创建完成端口
			NULL,								// 参数无效  完成端口句柄
			NULL,								// 参数无效   完成键
			info.dwNumberOfProcessors * 2		// 线程数量
		);
	if (hIoCompletionProt == INVALID_HANDLE_VALUE)
	{
		printf("创建完成端口失败\n");
		return 0;
	}
	// 6. 创建工作线程 - CPU核心数*2
	//      6.1 等待完成端口 GetQueuedCompletionStatus
	//      6.2 处理消息
	for (int i = 0; i < info.dwNumberOfProcessors * 2; i++)
	{
		CreateThread(
			NULL,
			NULL,
			WorkThread,			// 工作线程
			hIoCompletionProt, // 完成端口句柄
			NULL,
			NULL
		);
	}

	// 7. 等待连接
	while (TRUE)
	{
		SOCKADDR_IN ClinetAddress = {};  // 客户端地址信息
		int addrlen = sizeof(SOCKADDR_IN);
		// 等待客户链接,返回客户套接字句柄
		SOCKET ClientSock = accept(
			ServerSock,						// 服务端句柄
			(SOCKADDR*)&ClinetAddress,		// 客户地址信息
			&addrlen						// 地址大小
		);

		// 8. 将客户套接字与完成端口进行绑定
		CreateIoCompletionPort(
			(HANDLE)ClientSock,				// 关联的设备对象
			hIoCompletionProt,				// 完成端口对象
			NULL,							// 完成键,类似于线程的参数
			NULL							// 无效
		);

		// 9. 发起一个异步读IO请求


		DWORD dwReadSize = 0;
		DWORD dwFlags = 0;
		// 重叠IO结构体 必须非局部空间,new 
		MYOVERLAPPED* pov = 
			new MYOVERLAPPED(ClientSock, ClinetAddress);

		WSARecv(
			ClientSock,		// 接受数据套接字
			&pov->m_buff,	// 缓冲区结构体
			1,				// 缓冲区个数
			&dwReadSize,	// 实际字节数
			&dwFlags,		// 标志
			pov,			// 重叠IO
			NULL			// 完成时调用函数
		);

	};

	// 7. 关闭套接字             closesocket
	closesocket(ClinetSock);
	closesocket(ServerSock);

	// 8. 清空环境               WSACleanup
	WSACleanup();

	getchar();
	return 0;

}

IOCP 客户端

// 06_IOCP客户端.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

//使用之前先要获得 对方的IP  并且在同一个局域网之内
//对方的防火墙是关闭的
//ping 通对方的IP地址
//对方的服务器,	ServerSockaddr.sin_addr.S_un.S_addr =			// 网络IP地址inet_addr("127.0.0.1");
//此地址写的是自己的本机IP地址

#define _WINSOCK_DEPRECATED_NO_WARNINGS 

#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
#include<windows.h>
#include<stdio.h>

// 1. 初始化套接字环境       WSAStartup
// 2. 创建套接字             socket
// 3. 绑定套接字             bind     可以没有,系统自动分配

// 4. 发起连接               connect
// 5. 收发数据               send/recv
// 6. 关闭套接字             closesocekt
// 7. 清空环境               WSACleanup

int main()
{
	WSADATA data;
	// 1. 初始化套接字环境       WSAStartup
	if (WSAStartup(
		MAKEWORD(2, 2),		// 请求加载版本
		&data) != 0		  // 实际加载版本
		)
	{
		printf("初始化环境失败\n");
		return 0;
	}
	// 2. 创建套接字             socket
	SOCKET ClinetSock = socket(
		AF_INET,		//通讯协议
		SOCK_STREAM,	//套接字类型
		IPPROTO_TCP		//传输协议
	);

	if (ClinetSock == INVALID_SOCKET)
	{
		printf("创建套接字失败\n");
		return 0;
	}
	SOCKADDR_IN ServerSockAddr = {};			// 服务端地址信息
	int socklen = sizeof(sockaddr);				// 地址大小
	ServerSockAddr.sin_family = AF_INET;		// 网络协议
	ServerSockAddr.sin_port = htons(1234);		// 服务端的网络端口
	ServerSockAddr.sin_addr.S_un.S_addr =	    // 服务端的IP地址
		inet_addr("192.168.2.119");

	// 4. 发起连接               connect
	if (SOCKET_ERROR == connect(
		ClinetSock,						//客户端套接字
		(SOCKADDR*)&ServerSockAddr,		//服务端地址信息
		sizeof(SOCKADDR)				//地址长度
	))
	{
		printf("连接服务端失败\n");
		return 0;
	}

	printf("等待数据...\n");
	char buff[1024] = {};

	while (TRUE)
	{
		printf("<<: ");
		gets_s(buff, 1024);
		if (strcmp(buff, "quit") == 0)
		{
			// 下线了
			shutdown(ClinetSock, 0);
			break;
		}
		// 发送数据给服务端
		send(
			ClinetSock,
			buff,
			strlen(buff)+1,
			0);
		
	}



	// 7. 关闭套接字             closesocket
	closesocket(ClinetSock);

	// 8. 清空环境               WSACleanup
	WSACleanup();

	getchar();
	return 0;

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值