C++ Socket网络编程 简易服务端1.0版本搭建(一)

学习目标:
1、掌握多平台C++程序的设计、编码、调试和发布
2、掌握Select、IOCP、epoll 网络通信模型
3、掌握主流平台下使用C++ 进行TCP网络通信
4、掌握游戏引擎中使用C++ TCP通信
5、掌握后端开发性能优化技巧
6、掌握多线程、内存管理(内存池、对象池)的实现和运用

第一讲:运用C++和Socket API构建百万级处理能力网络通信引擎
首先感谢伟大的刘远东老师!!!

1、不到2000行代码的Select模型服务端程序
(1)Socket Select 模型客户端 SocketClient
(2)Socket Select 模型服务端 CELLSocketServer
(3)网络消息协议解封包结构 CELLSocket MessageHeader
(4)内存代理 CELLDelegate
(5)临界区锁 CELLMutex
(6)多线程 CELLThread
(7)精准计时器 CELLTimestamp

第一节:Socket基础API
Socket可以当成文件操作。
客户端中:建立一个Socket相当于声明一个文件指针;连接服务器相当于打开文件;向服务器发送数据相当于fwrite文件,接收服务端数据相当于fread文件;关闭连接相当于关闭文件。 客户端通过IP地址和端口号定向连接到服务器。
服务端中:7步实现网络交互。与客户端不同的是,服务端需要绑定端口,监听端口并阻塞等待客户端连接。服务端共3步阻塞,需要搭配多线程编程实现相应功能。
在这里插入图片描述
第二节:建立Windows Socket程序 (VS2015)

建立一个空的Win32控制台程序

#define WIN32_LEAN_AND_MEAN
#include<Windows.h>
#include<WinSock2.h>

#pragma comment(lib,"ws2_32.lib") //windows socket2 32的lib库

int main()
{
	//启动 windows socket 2.x 环境
	WORD versionCode = MAKEWORD(2, 2);	//创建一个版本号 
	WSADATA data;
	WSAStartup(versionCode, &data);  //启动Socket网络API的函数
									 ///

									 ///
	WSACleanup();
	return 0;
}

第三节: 建立建议的TCP服务端和客户端

(1) 用Socket API建立简易的TCP服务端

  1. 建立一个Socket
  2. 绑定接受客户端连接的端口 bind
  3. 监听网络端口 listen
  4. 等待接受客户端连接 accept
  5. 向客户端发送一条数据 send
  6. 关闭socket

定义建议服务端的基本SOCKET代码

#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<Windows.h>
#include<WinSock2.h>
#include<iostream>
#include<string>
using namespace std;
#pragma comment(lib,"ws2_32.lib") //windows socket2 32的lib库

int main()
{
	//启动 windows socket 2.x 环境
	WORD versionCode = MAKEWORD(2, 2);	//创建一个版本号 
	WSADATA data;
	WSAStartup(versionCode, &data);  //启动Socket网络API的函数
									 ///


	//(1) 用Socket API建立简易的TCP服务端

	//	1. 建立一个Socket
	SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // ipv4 面向字节流的 tcp协议

	//	2. 绑定接受客户端连接的端口 bind

	sockaddr_in _sin = {};
	_sin.sin_family = AF_INET;
	_sin.sin_port = htons(4567); //端口号 host to net  sockaddr_in中port是USHORT类型 网络中port是 unsigend short类型 因此需要Htons进行转换
	//_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  //服务器绑定的IP地址  127.0.0.1是本地地址
	_sin.sin_addr.S_un.S_addr = INADDR_ANY; //不限定访问该服务端的IP
	if (bind(_sock, (sockaddr*)&_sin, sizeof(_sin)) == SOCKET_ERROR)  //sockaddr 不利于编码  
	{
		cout << "ERROR: 绑定用于接受客户端连接的网络端口失败..." << endl;
	}
	else
	{
		cout << "SUCCESS: 绑定端口成功..." << endl;
	}
	//	3. 监听网络端口 listen

	if (listen(_sock, 5) == SOCKET_ERROR)//第二个参数 backbag 最大允许连接数量
	{
		cout << "ERROR: 监听用于接受客户端连接的网络端口失败..." << endl;
	}
	else
	{
		cout << "SUCCESS: 监听端口成功..." << endl;
	}

	//	4. 等待接受客户端连接 accept

	sockaddr_in _clientAddr = {};  
	int cliendAddrLen = sizeof(_clientAddr);
	SOCKET _clientSock = INVALID_SOCKET; // 初始化无效的socket 用来存储接入的客户端

	char msgBuf[] = "Hello, I'm Server";
	while (true)
	{
		_clientSock = accept(_sock, (sockaddr*)&_clientAddr, &cliendAddrLen);//当客户端接入时 会得到连入客户端的socket地址和长度
		if (INVALID_SOCKET == _clientSock) //接受到无效接入
		{
			cout << "ERROR: 接受到无效客户端SOCKET..." << endl;
		}
		else
		{
			cout << "新Client加入: IP = " << inet_ntoa(_clientAddr.sin_addr) << endl;  //inet_ntoa 将ip地址转换成可读的字符串
			//	5. 向客户端发送一条数据 send
			send(_clientSock, msgBuf, strlen(msgBuf) + 1, 0); //+1是为了把\0算进去
		}
	}

	//	6. 关闭socket
	closesocket(_sock);
	// 清除Windows socket环境
	WSACleanup();
	return 0;
}
//这段是socket地址中绑定IP地址时的数据结构  S_un是一个联合体
typedef struct in_addr {
        union {
                struct { UCHAR s_b1,s_b2,s_b3,s_b4; } S_un_b;
                struct { USHORT s_w1,s_w2; } S_un_w;
                ULONG S_addr;
        } S_un;
#define s_addr  S_un.S_addr /* can be used for most tcp & ip code */
#define s_host  S_un.S_un_b.s_b2    // host on imp
#define s_net   S_un.S_un_b.s_b1    // network
#define s_imp   S_un.S_un_w.s_w2    // imp
#define s_impno S_un.S_un_b.s_b4    // imp #
#define s_lh    S_un.S_un_b.s_b3    // logical host
} IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR;

(2) 用Socket API建立简易的TCP客户端

  1. 建立一个Socket
  2. 连接服务器 connect
  3. 接受服务器信息 recive
  4. 关闭 socket

猜你喜欢

转载自blog.csdn.net/La745739773/article/details/89034955