Socket简易封装

支持WIN32、Linux通信Socket简易封装

注:_WIN32实在MFC基础上封装的,可以去掉_WIN32部分。

一、封装.h.cpp

头文件Socket.h

#ifndef SOCKET_H
#define SOCKET_H

#ifdef _WIN32

#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#pragma comment(lib, "ws2_32.lib")
#include <WinSock2.h>
#include <string>

typedef int socklen_t;

#else
#include <string>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#define INVALID_SOCKET -1

typedef int SOCKET;
#endif // _WIN32

class Socket
{
	SOCKET m_hSocket;

public:
#ifdef _WIN32
	Socket(SOCKET sock = INVALID_SOCKET) : m_hSocket(sock)
	{
		static WSAData wd;
		if (wd.wVersion == 0)
			WSAStartup(0x0202, &wd);
	}
#else
	Socket(){};
	Socket(int sock) : m_hSocket(sock){};
#endif // _WIN32

	~Socket()
	{
		if (INVALID_SOCKET != m_hSocket)
		{
#ifdef _WIN32
			closesocket(m_hSocket);
#else
			close(m_hSocket);
#endif // _WIN32
		}
	}

	operator SOCKET() const
	{
		return m_hSocket;
	}
	
	//输出Error Info
	inline static void GetLastError()
	{
#ifdef _WIN32
		auto n = WSAGetLastError();
		printf("erron:%d\n", n);
		WSASetLastError(n);
#else
		printf("erron:%d info:%s\n", errno, strerror(errno));
#endif // _WIN32
	}

	//创建连接,
	//nSocketPort端口号、nSocketType连接模式(默认TCP)、
	//lpszSocketAddress选择创建链接的IP地址(默认0.0.0.0)
	bool Create(unsigned int nSocketPort = 0, int nSocketType = SOCK_STREAM, const char *lpszSocketAddress = NULL);
	
	//启动TCP服务端后、进行监听
	//nBacklog 挂起连接队列的最大长度。
	inline bool Listen(int nBacklog = 5)
	{
		return listen(m_hSocket, nBacklog);
	}

	//等待连接
	bool Accept(Socket &socka, char *sIP = nullptr, unsigned int *pPort = nullptr);
	
	//链接到对应IP、端口
	bool Connect(const char *lpszHostAddress, unsigned int nHostPort);
	
	//返回当前IP、主机端口info
	bool GetSockName(char *sIP, unsigned int &nPort);
	bool GetSockName(std::string &sIP, unsigned int &nPort);
	
	//返回Peer的IP、端口Info
	bool GetPeerName(char *sIP, unsigned int &nPort);
	bool GetPeerName(std::string &sIP, unsigned int &nPort);

	//关闭Socket
	inline void Close()
	{
#ifdef _WIN32
		closesocket(m_hSocket);
#else
		close(m_hSocket);
#endif // _WIN32
		m_hSocket = INVALID_SOCKET;
	}
	
	//接受buffer
	//lpBuf buffer地址 、 nBufLen buffer长度
	inline int Receive(void *lpBuf, int nBufLen, int nFlags = 0)
	{
		return recv(m_hSocket, static_cast<char *>(lpBuf), nBufLen, nFlags);
	}
	
	//接受buffer
	// sockfd socket句柄
	inline int RecvFrom(int sockfd, void *buf, size_t len, int flags,
						struct sockaddr *src_addr, socklen_t *addrlen)
	{
#ifdef _WIN32
		return recvfrom(sockfd, static_cast<char*>(buf), len, flags, src_addr, addrlen);
#else
		return recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
#endif // _WIN32
	}
	
	int ReceiveFrom(void *lpBuf, int nBufLen,
					char *sIP = nullptr, unsigned int *pPort = nullptr, int nFlags = 0);
	
	//发送buffer
	//lpBuf发送内容、nBufLen buffer长度
	inline int Send(const void *lpBuf, int nBufLen, int nFlags = 0)
	{
		return send(m_hSocket, static_cast<const char *>(lpBuf), nBufLen, nFlags);
	}
	
	//dest_addr目标IP
	inline int Sendto(int sockfd, const void *buf, size_t len, int flags,
					  const struct sockaddr *dest_addr, socklen_t addrlen)
	{
#ifdef _WIN32
		return sendto(sockfd, static_cast<const char *>buf, len, flags, dest_addr, addrlen);
#else
		return sendto(sockfd, buf, len, flags, dest_addr, addrlen);
#endif // _WIN32
	}
	
	//nHostPort目标端口、lpszHostAddress目标IP
	int SendTo(const void *lpBuf, int nBufLen,
			   unsigned int nHostPort, char *lpszHostAddress, int nFlags = 0);
	
};

#endif // !SOCKET_H

实现文件Socket.cpp

#include "Socket.h"

bool Socket::Create(unsigned int nSocketPort, int nSocketType, const char *lpszSocketAddress)
{
	m_hSocket = socket(AF_INET, nSocketType, IPPROTO_IP);
	if (INVALID_SOCKET == m_hSocket)
	{
		GetLastError();
		Close();
		return false;
	}
	sockaddr_in sa;
	sa.sin_family = AF_INET;
	sa.sin_port = htons(nSocketPort);
	if (lpszSocketAddress)
	{
#ifdef _WIN32
		sa.sin_addr.S_un.S_addr = inet_addr(lpszSocketAddress);
#else
		sa.sin_addr.s_addr = inet_addr(lpszSocketAddress);
#endif // _WIN32
	}
	else
		sa.sin_addr.s_addr = INADDR_ANY;
	int n = bind(m_hSocket, (sockaddr *)&sa, sizeof(sa));
	if (n)
	{
		GetLastError();
		Close();
		return false;
	}
	return true;
}

bool Socket::Accept(Socket &socka, char *sIP, unsigned int *pPort)
{
	if (sIP || pPort)
	{
		sockaddr_in sa;
		int len = sizeof(sa);
		socka.m_hSocket = accept(m_hSocket, (sockaddr *)&sa, (socklen_t *)&len);
		if (socka.m_hSocket == INVALID_SOCKET)
			return false;
		if (pPort)
			*pPort = htons(sa.sin_port);
		if (sIP)
			strcpy(sIP, inet_ntoa(sa.sin_addr));
	}
	else
		socka.m_hSocket = accept(m_hSocket, nullptr, nullptr);
	return socka.m_hSocket != INVALID_SOCKET;
}

bool Socket::Connect(const char *lpszHostAddress, unsigned int nHostPort)
{
	sockaddr_in sa;
	sa.sin_family = AF_INET;
	sa.sin_port = htons(nHostPort);
#ifdef _WIN32
	sa.sin_addr.S_un.S_addr = inet_addr(lpszHostAddress);
#else
	sa.sin_addr.s_addr = inet_addr(lpszHostAddress);
#endif // _WIN32
	return !connect(m_hSocket, (sockaddr *)&sa, sizeof(sa));
}

bool Socket::GetPeerName(std::string &sIP, unsigned int &nPort)
{
	sockaddr_in sa;
	int len = sizeof(sa);
	if (getpeername(m_hSocket, (sockaddr *)&sa, (socklen_t *)&len))
		return false;
	nPort = htons(sa.sin_port);
	sIP = inet_ntoa(sa.sin_addr);
	return true;
}

bool Socket::GetSockName(std::string &sIP, unsigned int &nPort)
{
	sockaddr_in sa;
	int len = sizeof(sa);
	if (getsockname(m_hSocket, (sockaddr *)&sa, (socklen_t *)&len))
		return false;
	nPort = htons(sa.sin_port);
	sIP = inet_ntoa(sa.sin_addr);
	return true;
}

bool Socket::GetPeerName(char *sIP, unsigned int &nPort)
{
	sockaddr_in sa;
	int len = sizeof(sa);
	if (getpeername(m_hSocket, (sockaddr *)&sa, (socklen_t *)&len))
		return false;
	nPort = htons(sa.sin_port);
	if (sIP)
		strcpy(sIP, inet_ntoa(sa.sin_addr));
	return true;
}

bool Socket::GetSockName(char *sIP, unsigned int &nPort)
{
	sockaddr_in sa;
	int len = sizeof(sa);
	if (getsockname(m_hSocket, (sockaddr *)&sa, (socklen_t *)&len))
		return false;
	nPort = htons(sa.sin_port);
	if (sIP)
		strcpy(sIP, inet_ntoa(sa.sin_addr));
	return true;
}

int Socket::SendTo(const void *lpBuf, int nBufLen, unsigned int nHostPort, char *lpszHostAddress, int nFlags)
{
	sockaddr_in sa;
	sa.sin_family = AF_INET;
	sa.sin_port = htons(nHostPort);
#ifdef _WIN32
	sa.sin_addr.S_un.S_addr = inet_addr(lpszHostAddress);
#else
	sa.sin_addr.s_addr = inet_addr(lpszHostAddress);
#endif // _WIN32
	return sendto(m_hSocket, (const char *)lpBuf, nBufLen, nFlags, (sockaddr *)&sa, (socklen_t)sizeof(sa));
}

int Socket::ReceiveFrom(void *lpBuf, int nBufLen, char *sIP, unsigned int *pPort, int nFlags)
{
	sockaddr_in sa;
	int len = sizeof(sa);
	int n = recvfrom(m_hSocket, (char *)lpBuf, nBufLen, nFlags, (sockaddr *)&sa, (socklen_t *)&len);
	if (n <= 0)
		return n;
	if (pPort)
		*pPort = htons(sa.sin_port);
	if (sIP)
		strcpy(sIP, inet_ntoa(sa.sin_addr));

	return n;
}

二、测试Demo

Service

#include <iostream>
#include "Socket.h"

using namespace std;

int main()
{
	Socket Service;
	
	Service.Create(8805);
	Service.Listen();
	Socket Recv;
	Service.Accept(Recv);
	char str[128]{ 0 };
	string IP;
	unsigned int Port;
	while (true)
	{
		Recv.GetSockName(IP, Port);
		cout << "\n" << IP.c_str() << "	" << Port << endl;

		Recv.GetPeerName(IP, Port);
		cout << "\n" << IP.c_str() << "	" << Port << endl;

		Recv.Receive(str, sizeof(str));
		cout << "\n" << str << endl;
	}
	return 0;
}

Client

#include "Socket.h"
#include <iostream>

using namespace std;

int main()
{
	Socket client;
	client.Create();
	client.Connect("192.168.169.127", 8805);
	string str;
	while (true)
	{
		cin >> str;
		client.Send(str.c_str(), str.length());
	}
	return 0;
}

三、测试结果

在这里插入图片描述

这上面的IP是我本地的IP,8805是Service的端口,56169是Client的端口。本来是想在虚拟机Linux下测试的,但是困了。
还有就是上面有一些强转的void*,这个封装是我在Linux下封装的,移到Windows上的vs2019时,它的一些方法就传char*类型的参数。

这个封装并不是很好,但是也是简化了一些操作吧。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值