IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> Windows C++ Socket 简单实现 -> 正文阅读

[C++知识库]Windows C++ Socket 简单实现

刚开始学习Windows下的网络编程,简单实现了一个能收发请求的服务端和客户端,还有一些地方没弄明白,先把代码放这,有空再回来整理。

tool.h和tool.cpp

主要定义了请求的包头和数据结构以及报文的序列化及反序列化。

参考内容:https://blog.csdn.net/chenbiyun940419/article/details/96455550

#include <iostream>
#include <vector>
#include <string>
#include <map>

enum OPT {
	LOGINMSGE,
	FRIEND_REQ,
	FRIEND_RES,
	CHAT_REQ,
	CHAT_RES
};

typedef struct dataheader {
	int opt;
} DATAHEADER;

typedef struct loginmsg : public dataheader {
	loginmsg() { opt = LOGINMSGE; }
	std::vector<std::string> vs;
} LOGINMSG;

typedef struct req_friend : public dataheader {
	req_friend() { opt = FRIEND_REQ; }
} REQ_FRIEND;

typedef struct res_friend : public dataheader {
	res_friend() { opt = FRIEND_RES; }
	std::map<int, std::string> mis;
} RES_FRIEND;

typedef struct req_chat : public dataheader {
	req_chat() { opt = CHAT_REQ; }
	std::string str;
} REQ_CHAT;

typedef struct res_chat :public dataheader {
	res_chat() { opt = CHAT_RES; }
	std::string str;
} RES_CHAT;


void printmessage(char* recvbuf, int& step);

void serialize(char* Det, const int* Src, int& step);
void deserialize(int* Det, const char* Src, int& step);

void serialize(char* sendBuf, const std::string& str, int& step);
void deserialize(std::string& str, const char* recvBuf, int& step);

void serialize(char* sendBuf, const std::vector<int>& vec, int& step);
void deserialize(std::vector<int>& vec, const char* recvBuf, int& step);

void serialize(char* sendBuf, const std::vector<std::string>& vec, int& step);
void deserialize(std::vector<std::string>& vec, const char* recvBuf, int& step);

void serialize(char* sendBuf, std::map<int, std::string>& m, int& step);
void deserialize(std::map<int, std::string>& m, const char* recvBuf, int& step);

void serialize(char* sendbuf, DATAHEADER& dataheader, int& step);
void deserialize(DATAHEADER& dataheader, char* recvbuf, int& step);

void serialize(char* sendbuf, LOGINMSG& loginmsg, int& step);
void deserialize(LOGINMSG& loginmsg, char* recvbuf, int& step);

void serialize(char* sendbuf, REQ_FRIEND& req_friend, int& step);
void deserialize(REQ_FRIEND& req_friend, char* recvbuf, int& step);

void serialize(char* sendbuf, RES_FRIEND& res_friend, int& step);
void deserialize(RES_FRIEND& res_friend, char* recvbuf, int& step);

void serialize(char* sendbuf, REQ_CHAT& req_chat, int& step);
void deserialize(REQ_CHAT& req_chat, char* recvbuf, int& step);

void serialize(char* sendbuf, RES_CHAT& res_chat, int& step);
void deserialize(RES_CHAT& res_chat, char* recvbuf, int& step);
#include <string.h>
#include "tool.h"

using namespace std;

void printmessage(char* recvbuf, int& step)
{
	string str;
	deserialize(str, recvbuf, step);
	cout << str << endl;
}

//int
void serialize(char* Det, const int* Src, int& step)
{
	memcpy(Det + step, Src, sizeof(int));
	step += sizeof(int);
}

void deserialize(int* Det, const char* Src, int& step)
{
	memcpy(Det, Src + step, sizeof(int));
	step += sizeof(int);
}

//string
void serialize(char* sendBuf, const string& str, int& step)
{
	int size;
	size = str.length();
	serialize(sendBuf, &size, step);
	memcpy(sendBuf + step, &str[0], size);
	step += size;
}

void deserialize(string& str, const char* recvBuf, int& step)
{
	int size;
	deserialize(&size, recvBuf, step);
	str = string(recvBuf + step, size);
	step += size;
}

//vector<int>
void serialize(char* sendBuf, const vector<int>& vec, int& step)
{
	int size = vec.size();
	serialize(sendBuf, &size, step);
	memcpy(sendBuf + step, &vec[0], size * sizeof(int));
	step += size * sizeof(int);
}

void deserialize(vector<int>& vec, const char* recvBuf, int& step)
{
	int size;
	deserialize(&size, recvBuf, step);
	vec.resize(size);
	memcpy(&vec[0], recvBuf + step, size * sizeof(int));
	step += size * sizeof(int);
}

//vector<string>
void serialize(char* sendBuf, const vector<string>& vec, int& step)
{
	int size = vec.size();
	serialize(sendBuf, &size, step);
	for (auto it = vec.begin(); it != vec.end(); it++)
		serialize(sendBuf, *it, step);
}

void deserialize(vector<string>& vec, const char* recvBuf, int& step)
{
	int size;
	deserialize(&size, recvBuf, step);
	string str;
	if (!vec.empty())
		vec.resize(0);
	for (int i = 0; i < size; i++)
	{
		deserialize(str, recvBuf, step);
		vec.insert(vec.end(), str);
	}

}

//map<int,string>
void serialize(char* sendBuf, map<int, string>& m, int& step)
{
	int size = m.size();
	serialize(sendBuf, &size, step);

	for (auto it = m.begin(); it != m.end(); it++)
	{
		serialize(sendBuf, &(it->first), step);
		serialize(sendBuf, it->second, step);
	}

}

void deserialize(map<int, string>& m, const char* recvBuf, int& step)
{
	int size;
	deserialize(&size, recvBuf, step);
	int int_first;
	string str_second;
	if (!m.empty())
		m.clear();
	for (int i = 0; i < size; i++)
	{
		deserialize(&int_first, recvBuf, step);
		deserialize(str_second, recvBuf, step);
		m.insert(pair<int, string>(int_first, str_second));
	}
}

void serialize(char* sendbuf, DATAHEADER& dataheader, int& step)
{
	serialize(sendbuf, &dataheader.opt, step);
}
void deserialize(DATAHEADER& dataheader, char* recvbuf, int& step)
{
	deserialize(&dataheader.opt, recvbuf, step);
}
void serialize(char* sendbuf, LOGINMSG& loginmsg, int& step)
{
	serialize(sendbuf, &loginmsg.opt, step);
	serialize(sendbuf, loginmsg.vs, step);
}
void deserialize(LOGINMSG& loginmsg, char* recvbuf, int& step)
{
	deserialize(loginmsg.vs, recvbuf, step);
}

void serialize(char* sendbuf, REQ_FRIEND& req_friend, int& step)
{
	serialize(sendbuf, &req_friend.opt, step);
}
void deserialize(REQ_FRIEND& req_friend, char* recvbuf, int& step)
{
	deserialize(&req_friend.opt, recvbuf, step);
}

void serialize(char* sendbuf, RES_FRIEND& res_friend, int& step)
{
	serialize(sendbuf, &res_friend.opt, step);
	serialize(sendbuf, res_friend.mis, step);
}
void deserialize(RES_FRIEND& res_friend, char* recvbuf, int& step)
{
	deserialize(res_friend.mis, recvbuf, step);
}

void serialize(char* sendbuf, REQ_CHAT& req_chat, int& step)
{
	serialize(sendbuf, &req_chat.opt, step);
	serialize(sendbuf, req_chat.str, step);
}
void deserialize(REQ_CHAT& req_chat, char* recvbuf, int& step)
{
	deserialize(req_chat.str, recvbuf, step);
}

void serialize(char* sendbuf, RES_CHAT& res_chat, int& step)
{
	serialize(sendbuf, &res_chat.opt, step);
	serialize(sendbuf, res_chat.str, step);
}
void deserialize(RES_CHAT& res_chat, char* recvbuf, int& step)
{
	deserialize(res_chat.str, recvbuf, step);
}

server.cpp?服务端实现

#define  _CRT_SECURE_NO_WARNINGS

#include <winsock2.h>
#include "tool.h"
#pragma comment (lib, "ws2_32.lib")

using namespace std;

#define SRVIP "127.0.0.1"
#define SRVPORT 6666

map<SOCKET, HANDLE> sh;

void logincheck(SOCKET& clientsocket, char* recvbuf, int& step)
{
	char sendbuf[1024] = {};
	memset(sendbuf, 0, sizeof(sendbuf));
	LOGINMSG loginmsg = {};
	deserialize(loginmsg, recvbuf, step);
	if (!strcmp(loginmsg.vs[0].c_str(), "luo") && !strcmp(loginmsg.vs[1].c_str(), "123456"))
	{
		loginmsg.vs[0] = "success";
		cout << "login success" << endl;
	}
	else
	{
		loginmsg.vs[0] = "fail";
		cout << "login fail" << endl;
	}
	step = 0;
	serialize(sendbuf, loginmsg, step);
	int ret = send(clientsocket, sendbuf, sizeof(sendbuf), 0);
	if (ret == -1 || ret == 0)
	{
		cout << "send error:" << strerror(errno) << " errno:" << errno << endl;
		return;
	}
}

void friendlist(SOCKET& clientsocket)
{
	RES_FRIEND res_friend = {};
	char sendbuf[1024] = {};
	int step = 0;
	res_friend.mis.insert(pair<int, string>(1, "qwert"));
	res_friend.mis.insert(pair<int, string>(2, "asdfgh"));
	res_friend.mis.insert(pair<int, string>(3, "zxcvbnm"));
	serialize(sendbuf, res_friend, step);
	int ret = send(clientsocket, sendbuf, sizeof(sendbuf), 0);
	if (ret == -1 || ret == 0)
	{
		cout << "send error:" << strerror(errno) << " errno:" << errno << endl;
		return;
	}
}

DWORD WINAPI sendmessage(const LPVOID param)
{
	SOCKET clientsocket = *(static_cast<SOCKET*>(param));
	char sendbuf[1024] = {};
	RES_CHAT res_chat = {};
	int step;
	while (1)
	{
		memset(&sendbuf, 0, sizeof(sendbuf));
		cout << "please input your message" << endl;
		cin >> res_chat.str;
		step = 0;
		serialize(sendbuf, res_chat, step);
		int ret = send(clientsocket, sendbuf, sizeof(sendbuf), 0);
		if (ret == -1 || ret == 0)
		{
			cout << "send error:" << strerror(errno) << " errno:" << errno << endl;
			break;
		}
	}
	return 0;
}

void chatmessage(SOCKET& clientsocket, char* recvbuf, int& step)
{
	printmessage(recvbuf, step);
	if (sh.find(clientsocket) == sh.end())
	{
		HANDLE sendThread;

		sendThread = CreateThread(NULL, 0, &sendmessage, &clientsocket, 0, NULL);
		sh.insert(pair<SOCKET, HANDLE>(clientsocket, sendThread));
	}
}

DWORD WINAPI run(const LPVOID param)
{
	SOCKET clientsocket = *(static_cast<SOCKET*>(param));
	char recvbuf[1024] = {};
	int step;
	DATAHEADER dataheader = {};

	while (1)
	{
		memset(recvbuf, 0, sizeof(recvbuf));
		int ret = recv(clientsocket, recvbuf, sizeof(recvbuf), 0);

		if (ret == 0 || ret == -1)
		{
			cout << "the client has closed" << endl;
			break;
		}
		cout << "get message from client" << endl;
		step = 0;
		deserialize(dataheader, recvbuf, step);
		switch (dataheader.opt)
		{
		case LOGINMSGE:
		{
			logincheck(clientsocket, recvbuf, step);
			break;
		}
		case FRIEND_REQ:
		{
			friendlist(clientsocket);
			break;
		}
		case CHAT_REQ:
		{
			chatmessage(clientsocket, recvbuf, step);
			break;
		}
		default:
		{
			cout << "req error" << endl;
			break;
		}
		}
	}
	closesocket(clientsocket);
	return 0;
}

int main()
{

	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);

	SOCKET serversocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (serversocket < 0)
	{
		cout << "create socket error:" << strerror(errno) << " errno:" << errno << endl;
		exit(0);
	}
	cout << "create socket success" << endl;


	sockaddr_in serverAddr;
	memset(&serverAddr, 0, sizeof(serverAddr));
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_port = htons((u_short)SRVPORT);
	serverAddr.sin_addr.s_addr = inet_addr(SRVIP);


	if (bind(serversocket, reinterpret_cast<sockaddr*>(&serverAddr), sizeof(sockaddr)) == -1)
	{
		cout << "bind error:" << strerror(errno) << " errno:" << errno << endl;
		exit(0);
	}
	cout << "bind success" << endl;


	if (listen(serversocket, 10) == -1)
	{
		cout << "listen error:" << strerror(errno) << " errno:" << errno << endl;
		exit(0);
	}
	cout << "listen success" << endl;

	HANDLE recvThread;

	while (1)
	{

		SOCKET conn_fd = accept(serversocket, NULL, NULL);
		if (conn_fd != -1)
			cout << "accppet a client" << endl;

		recvThread = CreateThread(NULL, 0, &run, &conn_fd, 0, NULL);
		CloseHandle(recvThread);
	}

	closesocket(serversocket);
	WSACleanup();
	return 0;
}

client.cpp?客户端实现

#define  _CRT_SECURE_NO_WARNINGS

#include <winsock2.h>
#include <windows.h>
#include "tool.h"
#pragma comment (lib, "ws2_32.lib")

using namespace std;

#define CLTIP "127.0.0.1"
#define SRVPORT 6666

bool logincheck(SOCKET& clientsocket)
{
	bool loginstate = false;
	int step;
	char sendbuf[1024] = {};
	char recvbuf[1024] = {};
	LOGINMSG loginmsg = {};
	string name, password;

	while (!loginstate)
	{
		memset(sendbuf, 0, sizeof(sendbuf));
		memset(recvbuf, 0, sizeof(recvbuf));
		if (!loginmsg.vs.empty())
			loginmsg.vs.resize(0);

		cout << "please input your name" << endl;
		cin >> name;
		loginmsg.vs.push_back(name);
		cout << "please input your password" << endl;
		cin >> password;
		loginmsg.vs.push_back(password);

		step = 0;
		serialize(sendbuf, loginmsg, step);

		int ret = send(clientsocket, sendbuf, sizeof(sendbuf), 0);
		if (ret == -1 || ret == 0)
		{
			cout << "send error:" << strerror(errno) << " errno:" << errno << endl;
			break;
		}
		ret = recv(clientsocket, recvbuf, sizeof(recvbuf), 0);
		if (ret == -1 || ret == 0)
		{
			cout << "the server close" << endl;
			break;
		}
		cout << "get message from server" << endl;

		DATAHEADER dataheader = {};
		step = 0;
		deserialize(dataheader, recvbuf, step);
		deserialize(loginmsg, recvbuf, step);
		if (!strcmp(loginmsg.vs[0].c_str(), "success"))
		{
			loginstate = true;
			cout << "login success" << endl;
		}
		else
			cout << "login fail" << endl;
	}
	return loginstate;
}

void printfriend(char* recvbuf, int& step)
{
	map<int, string> fl;
	deserialize(fl, recvbuf, step);
	for (auto it = fl.begin(); it != fl.end(); it++)
		cout << "<" << it->first << "," << it->second << ">" << " ";
	cout << endl;
}

void reqfriend(char* sendbuf)
{
	REQ_FRIEND req_friend = {};
	int step = 0;
	serialize(sendbuf, req_friend, step);
}

void reqchat(char* sendbuf)
{
	REQ_CHAT req_chat = {};
	int step = 0;
	cout << "please input your message" << endl;
	cin >> req_chat.str;
	serialize(sendbuf, req_chat, step);
}

DWORD WINAPI sendmessage(const LPVOID param)
{
	SOCKET clientsocket = *(static_cast<SOCKET*>(param));
	char sendbuf[1024] = {};
	int opt;

	while (1)
	{
		memset(&sendbuf, 0, sizeof(sendbuf));
	FLAG:   Sleep(500);
		cout << "please input your operator" << endl;
		cout << "1.friend map<int,string>" << endl;
		cout << "2.chat" << endl;
		cin >> opt;
		switch (opt)
		{
		case 1:
		{
			reqfriend(sendbuf);
			break;
		}
		case 2:
		{
			reqchat(sendbuf);
			break;
		}
		default:
		{
			cout << "error operator" << endl;
			goto FLAG;
		}
		}
		int ret = send(clientsocket, sendbuf, sizeof(sendbuf), 0);
		if (ret == -1 || ret == 0)
		{
			cout << "send error:" << strerror(errno) << " errno:" << errno << endl;
			break;
		}
	}
	closesocket(clientsocket);
	return 0;
}

int main()
{
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);

	SOCKET clientsocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (clientsocket < 0)
	{
		cout << "create socket error:" << strerror(errno) << " errno:" << errno << endl;
		exit(0);
	}
	cout << "create socket success" << endl;

	sockaddr_in clientAddr;
	memset(&clientAddr, 0, sizeof(clientAddr));
	clientAddr.sin_family = AF_INET;
	clientAddr.sin_port = htons((u_short)SRVPORT);
	clientAddr.sin_addr.s_addr = inet_addr(CLTIP);

	if (connect(clientsocket, reinterpret_cast<sockaddr*>(&clientAddr), sizeof(sockaddr)) < 0)
	{
		cout << "connect error:" << strerror(errno) << " errno:" << errno << endl;
		exit(0);
	}
	cout << "connect success" << endl;

	if (logincheck(clientsocket))
	{
		HANDLE sendThread;
		sendThread = CreateThread(NULL, 0, &sendmessage, &clientsocket, 0, NULL);
		CloseHandle(sendThread);

		char recvbuf[1024] = {};
		int step;

		while (1)
		{
			memset(recvbuf, 0, sizeof(recvbuf));
			int ret = recv(clientsocket, recvbuf, sizeof(recvbuf), 0);
			if (ret == -1 || ret == 0)
			{
				cout << "the server close" << endl;
				break;
			}
			cout << "get message from server" << endl;
			DATAHEADER dataheader = {};
			step = 0;
			deserialize(dataheader, recvbuf, step);
			switch (dataheader.opt)
			{
			case FRIEND_RES:
			{
				printfriend(recvbuf, step);
				break;
			}
			case CHAT_RES:
			{
				printmessage(recvbuf, step);
				break;
			}
			default:
			{
				cout << "error res" << endl;
				break;
			}
			}
		}
	}
	closesocket(clientsocket);
	WSACleanup();
	return 0;
}

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-16 11:33:49  更:2021-08-16 11:35:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 4:26:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码