C++封装TCP类,包括客户端和服务器

头文件 XTcp.h

#ifndef XTCP_H
#define XTCP_H

#ifdef WIN32
#ifdef XSOCKET_EXPORTS
#define XSOCKET_API __declspec(dllexport)
#else
#define XSOCKET_API __declspec(dllimport)
#endif
#else
#define XSOCKET_API
#endif

#include <string>
XSOCKET_API std::string GetIpByHost(std::string host);

//class XSOCKET_API XTcp
class XTcp
{
public:
	int CreateSocket();
	bool Bind(unsigned short port);
	XTcp Accept();
	void Close();
	int Recv(char *buf,int bufsize);
	int Send(const char *buf,int sendsize);
	bool Connect(const char *ip,unsigned short port,int timeoutms=1000);
	bool SetBlock(bool isblock);
	XTcp();
	virtual ~XTcp();
	int sock;
	unsigned short port;
	char ip[16];

};

#endif

源文件 XTcp.cpp

#include "XTcp.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define WIN32

#ifdef WIN32
#pragma comment(lib, "ws2_32.lib")
#include <windows.h>
#define socklen_t int
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <fcntl.h>
#define  closesocket close
#endif

//#include <thread>
using namespace std;
XSOCKET_API std::string GetIpByHost(std::string host)
{
	hostent *hptr = gethostbyname(host.c_str());
	if (!hptr)return "";
	in_addr addr;
	addr.s_addr = *(unsigned long *)hptr->h_addr;
	return inet_ntoa(addr);
}
XTcp::XTcp()
{
	sock = 0;
	port = 0;
#ifdef WIN32
	static bool first = true;
	if (first)
	{
		first = false;
		WSADATA ws;
		WSAStartup(MAKEWORD(2, 2), &ws);
	}
#endif
}
int XTcp::CreateSocket()
{
	sock = socket(AF_INET, SOCK_STREAM, 0);
	if (sock == -1)
	{
		printf("create socket failed!\n");
	}
	return sock;
}
bool XTcp::Bind(unsigned short port)
{
	if (sock <= 0)
		CreateSocket();
	sockaddr_in  saddr;
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(port);
	saddr.sin_addr.s_addr = htonl(0);
	if (::bind(sock, (sockaddr*)&saddr, sizeof(saddr)) != 0)
	{
		printf("bind port %d failed!\n", port);
		return false;
	}
	printf("bind port %d success!\n", port);
	listen(sock, 1000);
	return true;
}
int XTcp::Recv(char *buf, int bufsize)
{
	return recv(sock, buf, bufsize, 0);
}
int XTcp::Send(const char *buf, int size)
{
	int s = 0;
	while (s != size)
	{
		int len = send(sock, buf + s, size - s, 0);
		if (len <= 0)break;
		s += len;
	}
	return s;
}
void XTcp::Close()
{
	if (sock <= 0) return;
	closesocket(sock);
	sock = 0;
}
XTcp XTcp::Accept()
{
	XTcp tcp;
	sockaddr_in caddr;
	socklen_t len = sizeof(caddr);
	int client = accept(sock, (sockaddr*)&caddr, &len);
	if (client <= 0) return tcp;
	//printf("accept client %d\n", client);
	printf(".");
	char *ip = inet_ntoa(caddr.sin_addr);
	strcpy(tcp.ip, ip);
	tcp.port = ntohs(caddr.sin_port);
	tcp.sock = client;
	//printf("client ip is %s,port is %d\n", tcp.ip, tcp.port);
	return tcp;
}

bool XTcp::Connect(const char *ip,unsigned short port,int timeoutms)
{
	if(sock <=0 ) CreateSocket();
	sockaddr_in saddr;
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(port);
	saddr.sin_addr.s_addr = inet_addr(ip);
	SetBlock(false);
	fd_set set;
	if(connect(sock,(sockaddr*)&saddr,sizeof(saddr))!=0)
	{
		FD_ZERO(&set);
		FD_SET(sock,&set);
		timeval tm;
		tm.tv_sec = 0;
		tm.tv_usec = timeoutms*1000;
		if(select(sock+1,0,&set,0,&tm) <= 0)
		{
			printf("connect timeout or error!\n");
			printf("connect %s:%d failed!:%s\n",ip,port,strerror(errno));
			return false;
		}
	}
	SetBlock(true);
	printf("connect %s:%d success!\n",ip,port);
	return true;
}
XTcp::~XTcp()
{
}
bool XTcp::SetBlock(bool isblock)
{
	if(sock<=0) return false;
	#ifdef WIN32
		unsigned long ul = 0;
		if(!isblock) ul = 1;
		ioctlsocket(sock,FIONBIO,&ul);
	#else
		int flags = fcntl(sock,F_GETFL,0);
		if(flags<0)
			return false;
		if(isblock)
		{
			flags = flags&~O_NONBLOCK;
		}
		else
		{
			flags = flags|O_NONBLOCK;
		}
		if(fcntl(sock,F_SETFL,flags)!=0)
			return false;
	#endif
	return true;
}

服务器 server.cpp

#include <stdlib.h>
#include <windows.h>
#include "XTcp.h"
#include <string.h>
#include <iostream>


XTcp client;

DWORD WINAPI ThreadFunction(LPVOID lpParam) {
    // 线程要执行的代码
    char buf[1024] = {0};
	for (;;)
	{
		int recvlen = client.Recv(buf,sizeof(buf)-1);
		if (recvlen <= 0) break;
		buf[recvlen] = '\0';
				
		if (strstr(buf, "quit") != NULL)
		{
			char re[] = "quit success!\n";
			client.Send(re,strlen(re)+1);
			break;
		}
		int sendlen = client.Send("ok\n", 4);
		printf("recv %s\n",buf);
	}
	client.Close();
    return 0;
}

int main(int argc,char *argv[])
{
	unsigned short port = 8080;
	if (argc > 1)
	{
		port = atoi(argv[1]);
	}
	XTcp server;
	server.CreateSocket();
	server.Bind(port);
	for(;;)
	{
		client = server.Accept();
		// 创建线程
		HANDLE hThread;
		DWORD dwThreadId;
		hThread = CreateThread(
			NULL, // 安全属性
			0,    // 初始堆栈大小
			ThreadFunction, // 线程函数
			NULL, // 线程函数的参数
			0,    // 创建标志
			&dwThreadId); // 线程ID的指针
	}
	server.Close();
	getchar();
	return 0;
}

客户端 client.cpp

#include "XTcp.h"
#include <iostream>
#include <Windows.h>

int main()
{
	for(;;)
	{
		XTcp client;
		client.CreateSocket();
		client.SetBlock(false);
		client.Connect("127.0.0.1",8080,3000);

		char msg[1024] = "hhhh";
		int len = strlen(msg);
		client.Send(msg, strlen(msg));

		char buf[1024] = { 0 };
		client.Recv(buf, sizeof(buf));
		printf("%s\n", buf);

		client.Close();

		Sleep(10);
	}

	getchar();
}

运行结果

服务器

在这里插入图片描述

客户端

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/713805.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【git使用四】git分支理解与操作(详解)

目录 &#xff08;1&#xff09;理解git分支 主分支&#xff08;主线&#xff09; 功能分支 主线和分支关系 将分支合并到主分支 快速合并 非快速合并 git代码管理流程 &#xff08;2&#xff09;理解git提交对象 提交对象与commitID Git如何保存数据 示例讲解 &a…

Bio-Info每日一题:Rosalind-07-Mendel‘s First Law(孟德尔第一定律 python实现)

&#x1f389; 进入生物信息学的世界&#xff0c;与Rosalind一起探索吧&#xff01;&#x1f9ec; Rosalind是一个在线平台&#xff0c;专为学习和实践生物信息学而设计。该平台提供了一系列循序渐进的编程挑战&#xff0c;帮助用户从基础到高级掌握生物信息学知识。无论你是初…

C++前期概念(重)

目录 命名空间 命名空间定义 1. 正常的命名空间定义 2. 命名空间可以嵌套 3.头文件中的合并 命名空间使用 命名空间的使用有三种方式&#xff1a; 1:加命名空间名称及作用域限定符&#xff08;::&#xff09; 2:用using将命名空间中某个成员引入 3:使用using namespa…

Milvus Cloud 问答机器人 上线!构建企业级的 Chatbot

01. 背景 早些时候我们在社区微信群发出了一份关于Milvus Cloud 自动问答机器人的调研问卷。 调研受到了社区同学的积极响应,很快我们就收到了很多热心用户的回复。 基于这些回复,我们整理出了 Milvus Cloud Chatbot 的形态: 以功能使用和文档查询为核心 提供聊天和搜索双形…

【尚庭公寓SpringBoot + Vue 项目实战】图片上传(十)

【尚庭公寓SpringBoot Vue 项目实战】图片上传&#xff08;十&#xff09; 文章目录 【尚庭公寓SpringBoot Vue 项目实战】图片上传&#xff08;十&#xff09;1、图片上传流程2、图片上传接口查看3、代码开发3.1、配置Minio Client3.2、开发上传图片接口 4、异常处理 1、图片…

【每日刷题】Day66

【每日刷题】Day66 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 小乐乐改数字_牛客题霸_牛客网 (nowcoder.com) 2. 牛牛的递增之旅_牛客题霸_牛客网 (nowcoder.com)…

算法体系-20 第二十节暴力递归到动态规划

前言 动态规划模型从尝试暴力递归到傻缓存到动态规划 四种模型和体系班两种模型一共六种模型 0.1 从左往右模型 0.2 范围讨论模型范围尝试模型 &#xff08;这种模型特别在乎讨论开头如何如何 结尾如何如何&#xff09; 玩家博弈问题&#xff0c;玩家玩纸牌只能那左或者右 0.3 …

Docker Jenkins(改错版本)

Devops:它强调开发(Development)和运维(Operations)团队之间的协作.实现更快,更可靠的软件交付部署. JenKins是一个开源的自动化服务器,广泛用于构建,测试和部署软件项目.它是持续集成(CI)和持续交付/部署(CD)的工具.JenKins是实现DevOps实践的重要工具. 前端项目部署一般流程:…

【javaEE-有关CPU进程和线程实现的并发编程及二者的区别】

&#x1f525;&#x1f525;&#x1f525;有关进程并发编程开发的成本问题 这次之前其实我们所有的写的程序都是使用单核心来运行的&#xff0c;但是一般我们的计算机都有很多核心&#xff0c;如果我们编程的时候&#xff0c;只使用一个核心的话&#xff0c;其实这是一个非常大…

通俗范畴论2 有向图与准范畴

退一步海阔天空&#xff0c;在正式进入范畴论之前&#xff0c;我们可以重新审视一下我们是如何认识世界的&#xff0c;有了这个对人类认识世界过程的底层理解&#xff0c;可以帮助我们更好地理解范畴论。 对于人类认识世界&#xff0c;最神奇的一点就是这个世界居然是可以认识…

【C语言】解决C语言报错:Race Condition

文章目录 简介什么是Race ConditionRace Condition的常见原因如何检测和调试Race Condition解决Race Condition的最佳实践详细实例解析示例1&#xff1a;缺乏适当的同步机制示例2&#xff1a;错误使用条件变量 进一步阅读和参考资料总结 简介 Race Condition&#xff08;竞争条…

element-ui input输入框和多行文字输入框字体不一样

页面中未作样式修改&#xff0c;但是在项目中使用element-ui input输入框和多行文字输入框字体不一样&#xff0c;如下图所示&#xff1a; 这是因为字体不一致引起的&#xff0c;如果想要为Element UI的输入框设置特定的字体&#xff0c;你可以在你的样式表中添加以下CSS代码…

尚品汇-(二)

本地域名解析器&#xff1a;当我们在浏览器输入域名的时候&#xff0c;它首先找的不是远程的DNS&#xff0c;而是去本地的host中去找这个域名有没有对应的&#xff0c;如果有对应的&#xff0c;那么就根据对应的ip进行访问 一&#xff1a;环境安装 1.安装JAVA 运行环境 第一…

MySQL之优化服务器设置(四)

优化服务器设置 InnoDB的IO配置 双写缓冲(Doublewrite Buffer) InnoDB用双写缓冲来避免页没写完整所导致的数据损坏。当一个磁盘写操作不能完整地完成时&#xff0c;不完整的页写入就可能发生&#xff0c;16KB的页可能只有一部分被写到磁盘上。有多种多样的原因(崩溃、Bug&am…

Obsidian 工作区Workspace:实现切换和管理工作区的多任务处理插件

工作区 工作区是Obsidian 的核心插件之一&#xff0c;旨在帮助用户更好地管理和组织他们的工作环境。 功能简介 工作区保存和切换&#xff1a;Workspace 插件允许用户保存当前的窗口布局和打开的笔记状态&#xff0c;用户可以随时切换到不同的工作区&#xff0c;这样可以根据…

Matlab|基于手肘法的kmeans聚类数的精确识别【K-means聚类】

主要内容 在电力系统调度研究过程中&#xff0c;由于全年涉及的风、光和负荷曲线较多&#xff0c;为了分析出典型场景&#xff0c;很多时候就用到聚类算法&#xff0c;而K-means聚类就是常用到聚类算法&#xff0c;但是对于K-means聚类算法&#xff0c;需要自行指定分类数&…

Google Earth Engine(GEE)——计算闪闪红星的ndvi的值和折线图(时序分析)

函数: ui.Chart.image.doySeries(imageCollection, region, regionReducer, scale, yearReducer, startDay, endDay)

中小学电子教材下载办法(202406最简单的)

官方版本 现在能阅读电子教材的官方网站挺多的&#xff0c;例如 人民教育出版社-电子教材&#xff0c;还有 国家中小学智慧教育平台 &#xff0c;其他还有很多可在阅读的网站。由于平台的原因不能直接贴链接&#xff0c;大家可以通过搜索关键词找到网站。 如何下载 据我所知…

idea搜索只显示100条、如何修改idea搜索的条数

文章目录 一、老版本的IDEA&#xff08;2021年之前的版本&#xff09;二、新版本的IDEA&#xff08;2021年及之后的版本&#xff09;2.1、方式一2.2、方式二 如下图&#xff1a;idea搜索的时候默认只显示100条 要解决IDEA搜索只显示100条的问题&#xff0c;可以通过修改搜索结…