windows socket 封装 DLL 示例以及注意事项

见 socketmethod.h 和socketmethod.cpp代码以及注释,Visual Studio新建一个控制台程序,加入这两个文件,配置类型选为动态库(.dll),编译即可。

socketmethod.h 

/*This file provides basic windows socket methods*/
#pragma once
#ifdef _DLL_EXPORTS
#define DLL_API _declspec(dllexport)
#else
#define DLL_API _declspec(dllimport)
#endif // _DLL_EXPORTS

#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <vector>
namespace SocketMethod {
	class SocketServer {
	public:
		SocketServer(int PORT);
		~SocketServer();
		//Get the error code when initing
		virtual int GetErrorCode();
		//Close the server socket
		virtual void CloseSocketServer();
		//Close a client socket
		virtual void CloseSocketConn(SOCKET skt);
		//Clean all
		virtual void CleanSocket();
		//Clean all Socket Clients
		virtual void CleanSocketClients();

		//Wait for client to connect to this server.
		//If a connection comes it will be pushed to m_ClientSocketArray
		virtual SOCKET WaitAccept();
		//Get connected clients sockets of this server
		virtual std::vector<SOCKET> GetConnectedClients();
		//Get the Socket of this server
		virtual SOCKET GetSocketServer();
		//The buf needs to be malloced outside with size
		virtual bool Send(SOCKET sockConn, char* buf, int size);

		template<typename T>
		void FreeBasicArray(T& Array);

		//The recvBuf needs to be malloced outside with size.
		//If tcp error occured inside,recvBuf will be deleted and set nullptr.
		virtual void Receive(SOCKET sockConn, char*& recvBuf, unsigned int size);

	private:
		//The default port is 8001
		int m_DEFAULT_PORT = 8001;
		WORD	m_wVersionRequested;
		WSADATA m_wsaData;
		int		m_err, m_iLen;
		SOCKET m_sockSrv;
		SOCKADDR_IN m_addrSrv;
		SOCKET m_sockConn;
		int m_CurrentSize = 0;
		std::vector<SOCKET> m_ClientSocketArray;
		//State of initing process,0: no error, ohters:error
		int m_error = 0;
		//Init the socket server.
		//If fails returns -1
		int initSocketServer(int port);
	};

	template<typename T>
	inline void SocketServer::FreeBasicArray(T& Array) {
		if (Array != nullptr) {
			delete[] Array;
			Array = nullptr;
		}
	}

	class SocketClient
	{
		//TCP_SOCKET����
	private:
		WORD	wVersionRequested;
		WSADATA wsaData;
		int		err = 0, iLen = 0;
		int DEFAULT_PORT = 8001;
		SOCKET sockClt = 0;
		template<typename T>
		void FreeBasicArray(T& Array);
	public:
		//Init a socket client.
		//if error occurs,err will be set.
		SocketClient(int PORT = 8001);
		~SocketClient();
		//Get the socket of this client
		virtual SOCKET GetSocket();
		//Get the error when initing
		virtual int GetError();
		//The buf needs to be malloced outside with size
		virtual bool Send(SOCKET sockConn, char* buf, int size);
		//The recvBuf needs to be malloced outside with size.
		//If tcp error occured inside,recvBuf will be deleted and set nullptr.
		virtual void Receive(SOCKET sockConn, char*& recvBuf, unsigned int size);
		//Close a client socket
		virtual void CloseSocketConn(SOCKET skt);
	};

	template<typename T>
	inline void SocketClient::FreeBasicArray(T& Array) {
		if (Array != nullptr) {
			delete[] Array;
			Array = nullptr;
		}
	}
	//Create a Socket Server Inside Using new,UNABLE to delete it outside.
	//Use ReleaseSocketServer(SocketServer* sc) to release it.
	extern "C" DLL_API SocketServer * CreateSocketServer(int PORT);
	//Create a Socket Client Inside Using new,UNABLE to delete it outside. 
	//Use ReleaseSocketClient(SocketClient* sc) to release it.
	extern "C" DLL_API SocketClient * CreateSocketClient(int PORT);
	//ReleaseSocketClient will destroy the SocketClient Object,and close socket.
	extern "C" DLL_API void ReleaseSocketClient(SocketClient * sc);
	//ReleaseSocketServer will destroy the SocketServer Object,and close all sockets,clean up.
	extern "C" DLL_API void ReleaseSocketServer(SocketServer * sc);
}

socketmethod.cpp


#define _DLL_EXPORTS
#include "socketmethod.h"
namespace SocketMethod {
	SocketServer::SocketServer(int PORT) {
		initSocketServer(PORT);
	}

	SocketServer::~SocketServer() {
		CleanSocketClients();
		CloseSocketServer();
		CleanSocket();
	}

	int SocketServer::GetErrorCode()
	{
		return m_error;
	}

	void SocketServer::CloseSocketServer() {
		closesocket(m_sockSrv);
	}

	void SocketServer::CloseSocketConn(SOCKET skt) {
		closesocket(skt);
	}

	void SocketServer::CleanSocket() {
		WSACleanup();
	}

	void SocketServer::CleanSocketClients()
	{
		for (auto it = m_ClientSocketArray.begin(); it != m_ClientSocketArray.end(); it++) {
			closesocket(*it);
		}
	}

	SOCKET SocketServer::WaitAccept() {
		SOCKADDR_IN addrClt;
		int len = sizeof(SOCKADDR);
		SOCKET sockConn = accept(m_sockSrv, (SOCKADDR*)&addrClt, &len);
		m_ClientSocketArray.push_back(sockConn);
		return sockConn;
	}

	std::vector<SOCKET> SocketServer::GetConnectedClients()
	{
		return m_ClientSocketArray;
	}

	SOCKET SocketServer::GetSocketServer() {
		return m_sockSrv;
	}



	bool SocketServer::Send(SOCKET sockConn, char* buf, int size) {
		if (!(::send(sockConn, buf, size, 0) > 0)) {
			return false;
		}
		return true;
	}


	void SocketServer::Receive(SOCKET sockConn, char*& recvBuf, unsigned int size) {
		int len_want = size;
		int len_received = 0;
		while (1) {
			int iLen = recv(sockConn, recvBuf + len_received, len_want, 0);
			if (iLen == 0) {
				FreeBasicArray(recvBuf);
				break;
			}
			if (iLen == -1) {
				FreeBasicArray(recvBuf);
				break;
			}
			len_received += iLen; //�ݼ�
			len_want -= iLen;

			if (len_want == 0) {
				len_want = size;
				len_received = 0;
				break;
			}
		}
	}

	int SocketServer::initSocketServer(int port) {
		m_wVersionRequested = MAKEWORD(2, 2);//create 16bit data
		m_err = ::WSAStartup(m_wVersionRequested, &m_wsaData);	//load win socket
		if (m_err != 0)
		{
			return -1;
		}
		m_DEFAULT_PORT = port;
		m_addrSrv.sin_family = AF_INET;
		m_addrSrv.sin_addr.s_addr = ::htonl(INADDR_ANY);//Auto IP, byte sequence change
		m_addrSrv.sin_port = ::htons(m_DEFAULT_PORT);
		m_sockSrv = ::socket(AF_INET, SOCK_STREAM, 0);
		//(4)bind
		m_err = ::bind(m_sockSrv, (SOCKADDR*)&m_addrSrv, sizeof(SOCKADDR));
		if (m_err != 0)
		{
			return -2;
		}
		m_err = ::listen(m_sockSrv, 5);
		if (m_err != 0)
		{
			return -3;
		}
		return 0;
	}


	SocketClient::SocketClient(int PORT) {
		DEFAULT_PORT = PORT;
		wVersionRequested = MAKEWORD(2, 2);//create 16bit data
										   //(1)Load WinSock
		err = WSAStartup(wVersionRequested, &wsaData);	//load win socket
		if (err != 0)
		{
			err = -1;
			return;
		}
		//(2)create socket
		sockClt = socket(AF_INET, SOCK_STREAM, 0);
		if (sockClt == INVALID_SOCKET) {
			err = -2;
			return;
		}

		//(3)IP
		SOCKADDR_IN addrSrv;
		addrSrv.sin_family = AF_INET;
		inet_pton(AF_INET, "127.0.0.1", &addrSrv.sin_addr.S_un.S_addr);
		addrSrv.sin_port = htons(DEFAULT_PORT);

		//(5)connect
		err = connect(sockClt, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
		if (err == INVALID_SOCKET)
		{
			err = -3;
			return;
		}
		//TCP_SOCKET����
	}

	SocketClient::~SocketClient()
	{
		closesocket(sockClt);
	}

	SOCKET SocketClient::GetSocket() {
		return sockClt;
	}

	int SocketClient::GetError() {
		return err;
	}

	bool SocketClient::Send(SOCKET sockConn, char* buf, int size) {
		if (!(::send(sockConn, buf, size, 0) > 0)) {
			return false;
		}
		return true;
	}
	void SocketClient::Receive(SOCKET sockConn, char*& recvBuf, unsigned int size) {
		int len_want = size;
		int len_received = 0;
		while (1) {
			int iLen = recv(sockConn, recvBuf + len_received, len_want, 0);
			if (iLen == 0) {
				FreeBasicArray(recvBuf);
				break;
			}
			if (iLen == -1) {
				FreeBasicArray(recvBuf);
				break;
			}
			len_received += iLen; //�ݼ�
			len_want -= iLen;

			if (len_want == 0) {
				len_want = size;
				len_received = 0;
				break;
			}
		}
	}

	void SocketClient::CloseSocketConn(SOCKET skt) {
		closesocket(skt);
	}
	extern "C" DLL_API SocketServer * CreateSocketServer(int PORT) {
		return new SocketServer(PORT);
	}
	extern "C" DLL_API SocketClient * CreateSocketClient(int PORT) {
		return new SocketClient(PORT);

	}

	extern "C" DLL_API void ReleaseSocketClient(SocketClient * sc)
	{
		if (sc != nullptr)
		{
			delete sc;
			sc = nullptr;
		}

	}

	DLL_API void ReleaseSocketServer(SocketServer* ss)
	{
		if (ss != nullptr)
		{
			delete ss;
			ss = nullptr;
		}
	}
}

 注意事项:

1.#define _DLL_EXPORTS要放在#include "socketmethod.h" 前面。

2.使用命名空间。

说明:

这种方式导出是实际工程中用的最广泛的方式。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值