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();
}

运行结果

服务器

在这里插入图片描述

客户端

在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一个基于 Boost 库封装C++ Modbus TCP 客户端和服务端的示例代码: ```cpp #include <iostream> #include <string> #include <boost/asio.hpp> #include <boost/asio/ip/tcp.hpp> #include <boost/array.hpp> #include <boost/thread.hpp> using namespace std; using namespace boost::asio; using namespace boost::asio::ip; // Modbus TCP 帧结构体 #pragma pack(push, 1) struct ModbusTCPFrame { uint16_t transaction_id; uint16_t protocol_id; uint16_t length; uint8_t unit_id; uint8_t function_code; uint16_t start_address; uint16_t quantity; }; #pragma pack(pop) // Modbus TCP 客户端 class ModbusTCPClient { public: ModbusTCPClient(string ip_address, uint16_t port) : m_ip_address(ip_address), m_port(port), m_socket(m_io_service) { } // 连接到 Modbus TCP 服务器 bool connect() { try { m_socket.connect(tcp::endpoint(address::from_string(m_ip_address), m_port)); } catch (boost::system::system_error& e) { cerr << "Error: " << e.what() << endl; return false; } return true; } // 发送读取线圈状态请求 bool read_coils(uint16_t start_address, uint16_t quantity, boost::array<uint8_t, 256>& response) { ModbusTCPFrame frame = { 0 }; frame.transaction_id = 1; frame.protocol_id = 0; frame.length = 6; frame.unit_id = 1; frame.function_code = 0x01; frame.start_address = htons(start_address); frame.quantity = htons(quantity); boost::system::error_code ec; m_socket.write_some(buffer(&frame, 6), ec); if (ec) { cerr << "Error: " << ec.message() << endl; return false; } size_t len = m_socket.read_some(buffer(response), ec); if (ec) { cerr << "Error: " << ec.message() << endl; return false; } return true; } private: string m_ip_address; uint16_t m_port; io_service m_io_service; tcp::socket m_socket; }; // Modbus TCP 服务端 class ModbusTCPServer { public: ModbusTCPServer(uint16_t port) : m_port(port), m_acceptor(m_io_service, tcp::endpoint(tcp::v4(), m_port)) { } // 启动 Modbus TCP 服务器 void start() { boost::thread t(boost::bind(&io_service::run, &m_io_service)); while (true) { tcp::socket socket(m_io_service); m_acceptor.accept(socket); boost::thread(boost::bind(&ModbusTCPServer::handle_client, this, socket)); } } private: void handle_client(tcp::socket& socket) { boost::system::error_code ec; while (true) { boost::array<uint8_t, 256> request = { 0 }; size_t len = socket.read_some(buffer(request), ec); if (ec) { cerr << "Error: " << ec.message() << endl; break; } ModbusTCPFrame* frame = (ModbusTCPFrame*)request.data(); if (frame->function_code == 0x01) { uint16_t start_address = ntohs(frame->start_address); uint16_t quantity = ntohs(frame->quantity); boost::array<uint8_t, 256> response = { 0 }; response[0] = frame->transaction_id >> 8; response[1] = frame->transaction_id; response[2] = frame->protocol_id >> 8; response[3] = frame->protocol_id; response[4] = (quantity + 7) / 8; for (int i = 0; i < quantity; i++) { response[5 + i / 8] |= (i % 8 == 0 ? 0x80 : 0) | (i % 8 == 1 ? 0x40 : 0) | (i % 8 == 2 ? 0x20 : 0) | (i % 8 == 3 ? 0x10 : 0) | (i % 8 == 4 ? 0x08 : 0) | (i % 8 == 5 ? 0x04 : 0) | (i % 8 == 6 ? 0x02 : 0) | (i % 8 == 7 ? 0x01 : 0); } socket.write_some(buffer(response, 5 + (quantity + 7) / 8), ec); if (ec) { cerr << "Error: " << ec.message() << endl; break; } } } } private: uint16_t m_port; io_service m_io_service; tcp::acceptor m_acceptor; }; int main() { // 创建 Modbus TCP 客户端对象并连接到服务器 ModbusTCPClient client("127.0.0.1", 502); if (!client.connect()) { return -1; } // 发送读取线圈状态请求并输出结果 boost::array<uint8_t, 256> response = { 0 }; if (client.read_coils(0, 16, response)) { for (int i = 0; i < 16; i++) { cout << (response[5 + i / 8] & (1 << (i % 8)) ? "1" : "0"); } cout << endl; } // 创建 Modbus TCP 服务端对象并启动服务器 ModbusTCPServer server(502); server.start(); return 0; } ``` 该代码使用 Boost 库实现了 Modbus TCP 客户端和服务端。Modbus TCP 帧结构体使用了 pragma pack 指令进行字节对齐。ModbusTCPClient 实现了连接到 Modbus TCP 服务器和发送读取线圈状态请求的功能。ModbusTCPServer 实现了启动 Modbus TCP 服务器和处理客户端请求的功能。在 main 函数中先创建 Modbus TCP 客户端对象并连接到服务器,然后发送读取线圈状态请求并输出结果。接着创建 Modbus TCP 服务端对象并启动服务器,等待客户端连接并处理客户端请求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值