侧边栏壁纸
博主头像
Hope博主等级

努力赚钱的工科研究生

  • 累计撰写 362 篇文章
  • 累计创建 129 个标签
  • 累计收到 5 条评论
标签搜索

高性能服务器项目

Hope
2022-04-05 / 0 评论 / 0 点赞 / 481 阅读 / 3,173 字
温馨提示:
本文最后更新于 2022-04-07,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

1. Socket基础API

image.png

引入两个头文件。

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

image.png

但是发现会报错。

Windows.h一些定义较早,在WinSock2.h中也有定义,为了解决冲突,有两种方法。

  1. #define WIN32_LEAN_AND_MEAN
  2. #include<WinSock2.h>放在Windows.h前面

报错
image.png

解法方法:

  1. 链接器里面加入 ws2_32.lib
  2. 此方法只适用win系统 引入 #pragma comment(lib,"ws2_32.lib")

sockaddr_int 结构体

存放socket信息。

typedef struct sockaddr_in {

#if(_WIN32_WINNT < 0x0600)
    short   sin_family;
#else //(_WIN32_WINNT < 0x0600)
    ADDRESS_FAMILY sin_family;//AF_INET ip协议
#endif //(_WIN32_WINNT < 0x0600)

    USHORT sin_port; //port
    IN_ADDR sin_addr;//IP address, unsigned long
    CHAR sin_zero[8];// align
}

2. 简易Tcp服务端客户端 1.0

只能一次收发数据
Server:

#include <iostream>
#define WIN32_LEAN_AND_MEAN 
#include<Windows.h>
#include<WinSock2.h>
using namespace std;

/* 只能在win条件下
//调用 win 静态链接库
#pragma comment(lib,"ws2_32.lib")
*/


int main()
{
	//版本号
	WORD ver = MAKEWORD(2, 2);
	WSADATA dat;
	WSAStartup(ver, &dat);
	//1. 建立一个Socket
	//ipv4  字节流 tcp类型
	SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	//2. bind 绑定用于接受客户端连接的网路端口
	// 创建一个sockaddr 结构体 存放socket信息
	sockaddr_in _sin = {};

	_sin.sin_family = AF_INET;//指定ipv4协议 ipv6 AF_INET6
	_sin.sin_port = htons(4567); // host to net unsigned short

	//sin_addr  ... 是一个联合体 不是一个对象套对象
	//INADDR_ANY 不限定ip地址 任何一个都可以
	_sin.sin_addr.S_un.S_addr = INADDR_ANY;// inet_addr("127.0.0.1");

	if (SOCKET_ERROR == bind(_sock, (sockaddr*)&_sin, sizeof _sin)) {
		cout << "绑定端口失败" << endl;
	}
	else {
		cout << "绑定端口成功" << endl;
	}

	//3. listen 侦听端口
	//最大同时5个连接
	if (SOCKET_ERROR == listen(_sock, 5)) {
		cout << "监听端口失败" << endl;
	}
	else {
		cout << "监听端口成功" << endl;
	}

	//4 accept 等待接受客户端连接
	//这个socket接受的是客户端的信息
	sockaddr_in _clientAddr = { };
	int nAddrLen = sizeof _clientAddr;
	//int nAddrLen = sizeof sockaddr_in;
	//accept(_sock, (sockaddr*)&_clientAddr, &nAddrLen);
	//接受客户端的信息 socket 存到这个socket里面
	SOCKET _clientSocket = INVALID_SOCKET;
	char buff[] = "hello client,I am Server";
	while (true) {
		_clientSocket = accept(_sock, (sockaddr*)&_clientAddr, &nAddrLen);
		if (INVALID_SOCKET == _clientSocket) {
			cout << "接收到无效客户端socket" << endl;
		}
		cout << "新客户端加入" << "IP为:" << inet_ntoa(_clientAddr.sin_addr) << endl;

		//5. send 向客户端发送一条数据
		send(_clientSocket, buff, strlen(buff) + 1, 0);
	}

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

	WSACleanup();
	return 0;
}

client:

#include <iostream>
#define WIN32_LEAN_AND_MEAN 
#include<Windows.h>
#include<WinSock2.h>
//#define _WINSOCK_DEPRECATED_NO_WARNINGS
using namespace std;
int main()
{
	//版本号
	WORD ver = MAKEWORD(2, 2);
	WSADATA dat;
	WSAStartup(ver, &dat);
	//1. 建立一个Socket
	SOCKET _socket = socket(AF_INET, SOCK_STREAM, 0);
	if (INVALID_SOCKET == _socket) {
		cout << "错误,建立Socket失败" << endl;
	}
	else {
		cout << "成功,建立Socket成功" << endl;
	}

	//2. 连接服务器 connect
	sockaddr_in _sin = {};
	_sin.sin_family = AF_INET;
	_sin.sin_port = htons(4567);
	_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	if (INVALID_SOCKET == connect(_socket, (sockaddr*)(&_sin), sizeof _sin)) {
		cout << "连接服务器失败" << endl;
	}
	else {
		cout << "连接服务器成功" << endl;
	}
	//3. 接受服务器信息
	char rebuff[256] = {};
	//调用recv
	int nlen = recv(_socket, rebuff, 256, 0);
	if (nlen > 0) {
		cout << "接受到数据" << endl;
		printf("%s\n", rebuff);
	}
	//4. 关闭套接字
	closesocket(_socket);
	WSACleanup();
	getchar();
	return 0;
}

3. 可持续收发数据 1.1

image.png

0

评论区