linux下基础socket写的关于客户端,服务器的类

本文介绍了一个C++ Socket类的实现,包括服务端和客户端的创建、监听、接收、发送等功能,并利用多线程处理多个客户端连接请求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如有类似。纯属巧合。转载,请注明出处!API_Socket.cpp

#include "API_Define.hpp"
#include "API_Socket.hpp"
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>

typedef struct _SP_API_SOCKET_DATA
{
    API::API_Socket*	pApiSocket;
	struct sockaddr_in	addrClient;
	int			nSocket;
}SP_API_SOCKET_DATA, *PSP_API_SOCKET_DATA;

//构造函数
API::API_Socket::API_Socket()
{
	m_pCallBack = nullptr;
	m_zParam = nullptr;
	m_nSocket = 0;
}

//虚析构函数
API::API_Socket::~API_Socket()
{
}

//监听中
void API::API_Socket::Listening()
{
	while(m_nSocket)
	{
		PSP_API_SOCKET_DATA	pData = new SP_API_SOCKET_DATA;
		pData->pApiSocket = this;
		socklen_t		nAddrLength = sizeof(struct sockaddr);
		//LLPRINT("正在监听...\n");
		pData->nSocket = accept(m_nSocket, (struct sockaddr*)&(pData->addrClient), &nAddrLength);
		if(pData->nSocket > 0)
		{
			pthread_t	nPid;
			if(pthread_create(&nPid, nullptr, Thread_SubSocket, (void*)pData))
			{
				delete pData;
				LLERROR("创建套接字子线程失败");
			}
		}
	};
}

//发送或接收
bool API::API_Socket::SendRecv(int nSocket, void* pBuffer, int nLength, bool bSend)
{
	int	nCurrLength = nLength;
	int	nAction = 0;
	char*	pStr = (char*)pBuffer;
	//循环接收数据
	do{
		if(bSend)
		{
			nAction = send(nSocket, (char*)(pStr + nLength - nCurrLength), nCurrLength, 0);
		}
		else
		{
			nAction = recv(nSocket, (char*)(pStr + nLength - nCurrLength), nCurrLength, 0);
		}
		if(nAction == -1)
		{
			return false;
		}
		nCurrLength -= nAction;
	} while(nAction > 0 && nCurrLength);
	if(nCurrLength)
	{
		return false;
	}
	else
	{
		return true;
	}
}

//线程函数
void* API::API_Socket::Thread_Socket(void* zParam)
{
	API_Socket*	pThis = (API_Socket*)zParam;
	pThis->Listening();
	return nullptr;
}

//子线程函数
void* API::API_Socket::Thread_SubSocket(void* zParam)
{
	//获取数据并释放内存
	PSP_API_SOCKET_DATA	pData = (PSP_API_SOCKET_DATA)zParam;
	API_Socket*		pThis = pData->pApiSocket;
	int			nSocket = pData->nSocket;
	delete pData;
	//调用回调函数
	if(pThis->m_pCallBack)
	{
		pThis->m_pCallBack(pThis, nSocket, pThis->m_zParam);
	}
	return nullptr;
}

//创建Socket服务端
bool API::API_Socket::CreateServer(LPSOCKETCALLBACKEX pCallBack, int nPort, void* zParam, bool bWait)
{
	//保存参数
	m_pCallBack = pCallBack;
	m_zParam = zParam;

	//准备创建套接字
	m_nSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        struct sockaddr_in      addrServer;
        addrServer.sin_addr.s_addr = htonl(INADDR_ANY);		//目标IP
        addrServer.sin_family = AF_INET;
        addrServer.sin_port = htons((unsigned short)nPort);	//连接端口
        if(m_nSocket > 0)
        {
			//LLDEBUG("创建套接字成功");
		int	nEnable = 1;
		setsockopt(m_nSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&nEnable, sizeof(int));
		if(bind(m_nSocket, (struct sockaddr*)&addrServer, sizeof(struct sockaddr)) == 0)
		{
			//LLDEBUG("绑定套接字成功");
			if(listen(m_nSocket, 10) == 0)
			{
				//判断是否等待
				if(bWait)
				{
					//监听中
					Listening();
					return true;
				}
				else
				{
					pthread_t	nPid;
					if(!pthread_create(&nPid, nullptr, Thread_Socket, (void*)this))
					{
						return true;
					}
				}
			}
		}
		else
		{
			LLERROR("绑定套接字失败 error=%d", errno);
		}
        }
	else
	{
		LLERROR("创建套接字失败");
	}
	return false;
}

//创建Socket客户端
bool API::API_Socket::CreateClient(LPSOCKETCALLBACKEX pCallBack, const char* strServer, int nPort, void* zParam)
{
	//保存参数
	m_pCallBack = pCallBack;
	m_zParam = zParam;
	PSP_API_SOCKET_DATA	pData = new SP_API_SOCKET_DATA;

	m_nSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        //struct sockaddr_in      addrServer;
        pData->addrClient.sin_addr.s_addr = inet_addr(strServer);	//目标IP
        pData->addrClient.sin_family = AF_INET;
        pData->addrClient.sin_port = htons((unsigned short)nPort);	//连接端口
        if(m_nSocket > 0)
        {
		pData->pApiSocket = this;
		pData->nSocket = m_nSocket;
		//开始连接
                int     nConnect = connect(m_nSocket, (struct sockaddr*)&(pData->addrClient), sizeof(struct sockaddr));
                if(!nConnect)
                {
			pthread_t	nPid;
			if(pthread_create(&nPid, nullptr, Thread_SubSocket, (void*)pData) == 0)
			{
				//LLDEBUG("创建套接字线程成功");
				return true;
			}
			else
			{
				LLERROR("创建套接字线程失败");
			}
                }
        }
	delete pData;
        return false;
}

//接收
bool API::API_Socket::Recv(int nSocket, void* pBuffer, int nLength)
{
	return SendRecv(nSocket, pBuffer, nLength, false);
}

//发送
bool API::API_Socket::Send(int nSocket, void* pBuffer, int nLength)
{
	return SendRecv(nSocket, pBuffer, nLength, true);
}

//关闭套接字
void API::API_Socket::CloseSocket()
{
	close(m_nSocket);
}

下面这是头文件啦:

#ifndef			_API_SOCKET_HPP_
#define			_API_SOCKET_HPP_

#include "API_Define.hpp"

#define		NEURALNETWORK_NULL	0
#define		NEURALNETWORK_BEGIN	1
#define		NEURALNETWORK_END	2

//API命名空间
namespace API{


//套接字类
class API_Socket
{
	public:
		API_Socket();				//构造函数
		virtual ~API_Socket();			//虚析构函数

	private:	//内部成员变量
		int		m_nSocket;		//主套接字
		LPSOCKETCALLBACKEX	m_pCallBack;	//回调函数
		void*		m_zParam;		//回调函数参数

	private:	//内部成员函数
		virtual void Listening();		//监听中
		virtual bool SendRecv(int nSocket, void* pBuffer, int nLength, bool bSend);	//发送或接收

	public:		//静态成员函数
		static void* Thread_Socket(void* zParam);			//线程函数
		static void* Thread_SubSocket(void* zParam);			//子线程函数

	public:		//导出成员函数
		virtual bool CreateServer(LPSOCKETCALLBACKEX pCallBack, int nPort, void* zParam, bool bWait = false);		//创建Socket服务端
		virtual bool CreateClient(LPSOCKETCALLBACKEX pCallBack, const char* strServer, int nPort, void* zParam);		//创建Socket客户端
		virtual bool Recv(int nSocket, void* pBuffer, int nLength);	//接收
		virtual bool Send(int nSocket, void* pBuffer, int nLength);	//发送
		virtual void CloseSocket();					//关闭套接字
};
};
#endif//_API_SOCKET_HPP_
这个文件
API_Define.hpp"
在那呢?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Teleger

你的支持是我前进的方向

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

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

打赏作者

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

抵扣说明:

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

余额充值