ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

封装一个TCP客户端类

2022-02-28 17:03:52  阅读:263  来源: 互联网

标签:TcpClient 封装 thread TCP step mutex link my 客户端


TCPClient

写一个Windows环境下的TCP客户端,功能比较简单。
创建一个对象,即可连上服务器;并应用了一个有限状态机,在与服务器断开连接时,会自动尝试与服务器建立连接;在接收发送数据上,仅做测试通讯是否正常,被动接收数据,然后再把数据发送回给服务器;其中用到的my_std_thread.h,在另一篇文章有介绍


TcpClient.h

#pragma once
#include <WinSock2.h>
#include <stdio.h>
#include "my_std_thread.h"
using namespace std;

class TcpClient
{
private:
	SOCKET					sclient_ = INVALID_SOCKET;	
	const char*				ip_ = NULL;					
	u_short					port_ = 0;
private:
	my_std_thread			my_thread_;  
	my_std_thread::Thread   thread_id_;			
	int						link_step_;			
	my_std_thread::Mutex    link_step_mutex_;	
	my_std_thread::Mutex    send_mutex_;		

private:

	/*************************************************
	 * 函数名: 线程函数
	 * 描述 : 开启线程
	 * 输入 : 无
	 * 输出 : 无
	 * 返回值 : 无
	*************************************************/
	void ThreadWhile(void* arg);
	/*************************************************
	 * 函数名: 连接服务器
	 * 描述 :
	 * 输入 : 无
	 * 输出 : 无
	 * 返回值 : true/false
	*************************************************/
	bool LinkServer();
	/*************************************************
	 * 函数名: 初始化
	 * 描述 : 准备TCP通讯所需的环境
	 * 输入 : 无
	 * 输出 : 无
	 * 返回值 : 0/1
	*************************************************/
	int Initialize();
	/*************************************************
	 * 函数名: 开始
	 * 描述 : 客户端开始运行
	 * 输入 : 无
	 * 输出 : 无
	 * 返回值 : true
	*************************************************/
	bool Start();
public:
	/*************************************************
	 * 函数名: 
	 * 描述 :连接状态
	 * 输入 : 无
	 * 输出 : 无
	 * 返回值 : true表示连接上,false表示已断开
	*************************************************/
	bool ConnectStatus();
	/*************************************************
	 * 函数名: 
	 * 描述 : 给服务器发送数据
	 * 输入 : 无
	 * 输出 : 无
	 * 返回值 : 1/0
	*************************************************/
	int Send(const char* buffer, int len);
	/*************************************************
	 * 函数名: 发送
	 * 描述 : 构造函数
	 * 输入 : 无
	 * 输出 : 无
	 * 返回值 : 
	*************************************************/
	TcpClient(const char* ip, u_short port);
	/*************************************************
	 * 函数名: 
	 * 描述 : 析构函数
	 * 输入 : 无
	 * 输出 : 无
	 * 返回值 : 
	*************************************************/
	~TcpClient();
};



TcpClient.h

#include "TCPClient.h"
#include <string>
#include <iostream>
#include <thread>
#pragma comment(lib,"ws2_32.lib")
using namespace std;



/*************************************************
 * 函数名: 初始化 
 * 描述 : 准备TCP通讯所需的环境
 * 输入 : 无
 * 输出 : WSAStartup Failed/Success 
 * 返回值 : 0/1
*************************************************/
int TcpClient::Initialize() {

	WORD version = MAKEWORD(2, 2);
	WSADATA data;
	
	if (WSAStartup(version, &data) != 0) {
		std::cout << "WSAStartup Failed!"<<std::endl;
		return 0;
	}
	
	std::cout << "WSAStartup Success!"<<std::endl;
	return 1;
//	return 1;
}



/*************************************************
 * 函数名: 开始
 * 描述 : 客户端开始运行
 * 输入 : 无
 * 输出 : 无
 * 返回值 : true
*************************************************/

bool TcpClient::Start() {
	
	this->Initialize();

	my_thread_.createThread(thread_id_, &TcpClient::ThreadWhile,this,NULL);
	return true;
}

/*************************************************
 * 函数名: 连接服务器
 * 描述 :
 * 输入 : 无
 * 输出 : 无
 * 返回值 : true/false
*************************************************/

bool TcpClient::LinkServer()
{
	bool ret = false;
	if (sclient_>0) {
		closesocket(sclient_);
	}
	sclient_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	sockaddr_in servAddr;
	servAddr.sin_family = AF_INET;
	servAddr.sin_port = htons(port_);
	servAddr.sin_addr.S_un.S_addr = inet_addr(ip_);

	if (connect(sclient_, (LPSOCKADDR)&servAddr, sizeof(servAddr)) == SOCKET_ERROR )
	{
		std::cout << "Connect Failed!" << std::endl;
		ret = false;
	}
	else {
		std::cout << "Connect Success!" << std::endl;
		ret = true;
	}
	return ret;
}


/*************************************************
 * 函数名: 发送
 * 描述 : 给服务器发送数据
 * 输入 : 无
 * 输出 : 无
 * 返回值 : 1/0
*************************************************/

int TcpClient::Send(const char* buffer, int len) {
	if (!ConnectStatus()) {
		return -1;
	}
	my_thread_.lock(send_mutex_);
	int flag = send(sclient_,buffer,len,0);
	my_thread_.unlock(send_mutex_);
	if (flag== len) {
		std::cout << "Send Success!" << std::endl;
		return 1;
	}
	std::cout << "Send Failed!" << std::endl;
	return 0;
}

/*************************************************
 * 函数名: 连接状态
 * 描述 : 
 * 输入 : 无
 * 输出 : 无
 * 参数 : 无
 * 返回值 : true表示连接上,false表示已断开
*************************************************/
bool TcpClient::ConnectStatus() {
	bool ret = false;
	my_thread_.lock(link_step_mutex_);
	if (link_step_>0) {
		ret=  true;
	}
	my_thread_.unlock(link_step_mutex_);
	return ret;
}


/*************************************************
 * 函数名: 线程函数
 * 描述 : 类内开启线程
 * 输入 : 无
 * 输出 : 无
 * 参数 : 无
 * 返回值 : 无
*************************************************/

void TcpClient::ThreadWhile(void* arg)
{
	unsigned char buffer[4096] = { 0 };
	int ret = 0;

	while (1) {
		switch (link_step_) {
		case 0:
			if (LinkServer()) {
				link_step_++;
				break;
			}
			break;
		case 1:
			ret = recv(sclient_, (char*)buffer, sizeof(buffer), 0);
			// -1 接收失败  0 断开连接 
			if (ret <= 0) {
				link_step_ = 0;
				break;
			}
			else {
				Send((char*)buffer,ret);
			}
			break;
		default:
			break;
		}
	}
}

/*************************************************
 * 函数名: 
 * 描述 : 构造函数
 * 输入 : 无
 * 输出 : 无
 * 返回值 :
*************************************************/
TcpClient::TcpClient(const char* ip, u_short port) {
	
	ip_ = ip;
	port_ = port;

	thread_id_ = NULL;
	link_step_mutex_ = NULL;
	send_mutex_ = NULL;
	my_thread_.createMutex(link_step_mutex_);
	my_thread_.createMutex(send_mutex_);
	link_step_ = 0;
	sclient_ = INVALID_SOCKET;
	Start();
}

/*************************************************
 * 函数名:
 * 描述 : 析构函数
 * 输入 : 无
 * 输出 : 无
 * 返回值 :
*************************************************/
TcpClient::~TcpClient() {
	if (sclient_ != INVALID_SOCKET) {
		closesocket(sclient_);
	}
	my_thread_.deleteMutex(link_step_mutex_);
	my_thread_.deleteMutex(send_mutex_);
	WSACleanup();
	sclient_ = INVALID_SOCKET;
}

标签:TcpClient,封装,thread,TCP,step,mutex,link,my,客户端
来源: https://blog.csdn.net/weixin_44797811/article/details/123186076

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有