C++ Windows实现EchoServer非阻塞客户端(TPC协议)

介绍

C++ Windows实现EchoServer非阻塞客户端(TPC协议)
服务端文章在:http://t.csdnimg.cn/tCpOD
Windows IDE:Visual Studio 2022
我们将采用分文件编写方式

支持库

#include <string>
#include <winsock2.h>

代码

main.h

#pragma once
#define _WINSOCK_DEPRECATED_NO_WARNINGS
 
#include <string>
#include <winsock2.h>
 
#pragma comment(lib, "ws2_32.lib")
 
class EchoClient
{
private:
	SOCKET socketFD = 0;
	WORD sockVersion;
	WSADATA data;
	int InitCode;
 
	timeval timeout{};
 
	sockaddr_in serAddr{};
 
	fd_set wait{};
 
	int bufferSize = 1024;

    bool block;
 
public:
	EchoClient();
	~EchoClient();
 
	int connectServer(std::string ip, int port, bool noBlock = true);
 
	int sendServerDate(std::string date);
 
	void closeConnect();
 
	void setTimeout(int s = 3, int us = 0);
 
	std::string getServerDate();
};

main.cpp

#include "main.h"
 
EchoClient::EchoClient()
{
	sockVersion = MAKEWORD(2, 2);
	InitCode = WSAStartup(sockVersion, &data);
	setTimeout();
}
 
EchoClient::~EchoClient()
{
	WSACleanup();
}
 
int EchoClient::connectServer(std::string ip, int port, bool noBlock) {
	if (InitCode != 0)
		return -3;
 
	socketFD = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (socketFD == INVALID_SOCKET)
		return -2;
 
	if (noBlock) {
		u_long on = 1;
		if (ioctlsocket(socketFD, FIONBIO, &on) < 0) {
			return -4;
		}
	}

	block = !noBlock;

	serAddr.sin_family = AF_INET;
	serAddr.sin_port = htons(port);
	serAddr.sin_addr.S_un.S_addr = inet_addr(ip.c_str());
	int ret = connect(socketFD, (sockaddr*)&serAddr, sizeof(serAddr));

	if (block) {
		if (ret >= 0)
			return 0;
		else
			return -1;
	}

	if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK) {
		return -2;
	}
 
	FD_ZERO(&wait);
	FD_SET(socketFD, &wait);
 
	timeval tv = timeout;
	ret = select(socketFD + 1, NULL, &wait, NULL, &tv);
 
	if (ret == 0) {
		return -1;
	}
	else if (ret < 0) {
		return -2;
	}
 
	return 0;
}
 
int EchoClient::sendServerDate(std::string date)
{
	int code = send(socketFD, date.c_str(), date.size(), 0);
	return code;
}
 
void EchoClient::closeConnect()
{
	closesocket(socketFD);
}
 
void EchoClient::setTimeout(int s, int us)
{
	timeout.tv_sec = s;
	timeout.tv_usec = us;
}
 
std::string EchoClient::getServerDate()
{
	std::string result = "";
	char * buffer = new char[bufferSize];
	int len = 0,ready;
	buffer[len] = '\0';

	timeval tv = timeout;
	FD_ZERO(&wait);
	FD_SET(socketFD, &wait);

	while (true)
	{
		if (block)
			goto getMessage;
		ready = select(socketFD + 1, &wait, NULL, NULL, &tv);
		if (ready > 0) {
			if (FD_ISSET(socketFD, &wait)) {
			getMessage:
				len = recv(socketFD, buffer, bufferSize - 1, 0);
				if (len > 0) {
					buffer[len] = '\0';
					result.append(buffer);
					if (block)
						continue;
				}	
				else 
					break;
			}
		}
		else
			break;
	}
	delete[] buffer;
	return result;
}

示例

假设服务端地址:192.168.2.2 | 端口是1001

#include "main.h"
#include <iostream>
 
int main()
{
	std::string ip = "192.168.2.2";
	EchoClient ehoClient;
	while (true)
	{
		std::cout << "开始连接:" << ip;
		if (ehoClient.connectServer(ip, 1001) == 0) {
			ehoClient.setTimeout(1);
			ehoClient.sendServerDate("hello");
			std::string result = ehoClient.getServerDate();
			std::cout << "[Success] 发送数据:hello | 返回数据:" << result << "\n";
			if (result == "close") {
				std::cout << "Find:" << ip;
				ehoClient.closeConnect();
				break;
			}
				
		}
		else {
			std::cout << "[Fail]\n";
		}
	}
	return 0;
 
}

这里展示一下局域网快速搜索
假设局域网IP段是192.168.222 | 端口是1001

#include "main.h"
#include <iostream>
 
int main()
{
	std::string ipBasic = "192.168.222.";
	std::string ip = "";
	uint8_t i = 0;
	EchoClient ehoClient;
 
	ehoClient.setTimeout(0,1000);
	while (true)
	{
		ip = ipBasic + std::to_string(i++);
		std::cout << "开始连接:" << ip;
		if (ehoClient.connectServer(ip, 1001) == 0) {
			ehoClient.setTimeout(1);
			ehoClient.sendServerDate("hello");
			std::string result = ehoClient.getServerDate();
			std::cout << "[Success] 发送数据:hello | 返回数据:" << result << "\n";
			if (result == "close") {
				std::cout << "Find:" << ip;
				ehoClient.closeConnect();
				break;
			}
				
		}
		else {
			std::cout << "[Fail]\n";
		}
	}
	return 0;
 
}

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

STHUDY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值