好友
阅读权限10
听众
最后登录1970-1-1
|
liv
发表于 2019-3-20 17:53
LwTcpServer服务器和LwTcpClient客户端类 Win32 api Udp Scoket的封装
一、众所周知, win32 api 有"神奇"之效, 只要将它们样拼积木一样堆在一起,就能实现很多很酷的东西, 但是它的数量太多, 仅微软文档开放出来足足有三千多个并且参数类型各种宏定义,
使用时出了问题时常让我们摸不头脑, 查msdn也是很消耗时间, 所以要将这些 Win Api 分门别类 的封装起来, 以后方便使用. 当然做简单的封装就可以了, 不需要样mfc或者是Qt那样
二、相于Udp(User Datagram Protocol) 是一种无连接, 不可靠的传输层协议, 服务端与客户端在底层接口上没有明确区别, 一个主机节点是客户端还是服务端取决于你开发时的业务,
所以udp socket只要封装一个类就行
而 Tcp(Transmission Control Protocol) 是一种有连接, 可靠的传输层协议, 服务端与客户端在底层接口就有明确区别, , 所以 tcp socket 要封装成两个类(客户端与服务端), 曾经我将这些
接口封装成一个类, 经常造成服务端与客户端的接口混用
三、服务端类(LwTcpServer)
同样根据创建tcp服务端的流程来封装方法: 初始化网络环境 -> 创建TcpSocket -> 绑定端口 -> 监听 -> 等待客户端连接 -> 通序(收/发信息) -> 释放TcpSocket -> 清除网络环境 . 封装成如下方法:
[C++] 纯文本查看 复制代码 LwTcpServer(char* ip, int port); // 初始化网络环境并创建TcpSocket
~LwTcpServer(); // 释放TcpSocket并清除网络环境
bool Listen(int num); // 绑定并监听
int Accept(sockaddr_in* clientAddr); // 用户连接
int Send(int clientSocket, char* data, int len); // 发送消息
int Recv(int clientSocket, char* data, int len); // 接收数据
当然有些流程, 可以合并一起在一个方法处理. 与上一篇关于udp文章一样, tcp接收数据时(Recv方法), data 缓冲区的长度如果是512, 那么len就必须要小于512, 否则会返回-1
LwTcpServer.h
[C++] 纯文本查看 复制代码 #ifndef __LW_TCPSERVER_H__
#define __LW_TCPSERVER_H__
#include <WinSock2.h>
#include <Windows.h>
#pragma comment (lib, "WS2_32.lib")
// tcp服务器
class LwTcpServer
{
private:
SOCKET _socket; // 服务器socket
char* _ip; // ip
int _port; //端口
public:
LwTcpServer(char* ip, int port);
~LwTcpServer();
bool Listen(int num); // 监听
int Accept(sockaddr_in* clientAddr); // 接收进来用户
int Send(int clientSocket, char* data, int len); // 发送消息
int Recv(int clientSocket, char* data, int len); // 接收数据
};
#endif // !__LW_TCPSERVER_H__
LwTcpServer.cpp
[C++] 纯文本查看 复制代码 #include "LwTcpServer.h"
#include "LwNetworkInterface.h" // 需要这个类辅助
LwTcpServer::LwTcpServer(char* ip, int port)
{
LwNetworkInterface::InitWinsock();
this->_socket = socket(AF_INET, SOCK_STREAM, 0);
this->_ip = ip;
this->_port = port;
}
LwTcpServer::~LwTcpServer()
{
if (this->_socket != INVALID_SOCKET)
{
::closesocket(this->_socket);
}
LwNetworkInterface::ClearWinsock();
}
bool LwTcpServer::Listen(int num)
{
sockaddr_in address = LwNetworkInterface::CreateSocketAddr(this->_ip, this->_port);
bool ret = ::bind(this->_socket, (sockaddr*)&address, sizeof(address)) != SOCKET_ERROR;
return ret && ::listen(this->_socket, num) != SOCKET_ERROR;
}
int LwTcpServer::Accept(sockaddr_in* clientAddr)
{
int addrLen = sizeof(*clientAddr);
return ::accept(this->_socket, (sockaddr*)clientAddr, &addrLen);
}
int LwTcpServer::Send(int clientSocket, char* data, int len)
{
return ::send(clientSocket, data, len, 0);
}
int LwTcpServer::Recv(int clientSocket, char* data, int len)
{
return ::recv(clientSocket, data, len, 0);
}
四、客户端类(LwTcpClient)
同样根据创建tcp客户端的流程来封装方法: 初始化网络环境 -> 创建TcpSocket -> 连接服务端 -> 通序(收/发信息) -> 释放TcpSocket -> 清除网络环境 . 封装成如下方法:
[C++] 纯文本查看 复制代码 LwTcpClient(char* serverIp, int serverPort); // 初始化网络环境,创建socket
~LwTcpClient(); // 释放socket, 清除网络环境
bool Connect(); // 连接服务器
int Send(char* data, int len); // 发送数据
int Recv(char* data, int len); // 接收数据
LwTcpClient.h
[C++] 纯文本查看 复制代码 #ifndef __LW_TCPCLIENT_H__
#define __LW_TCPCLIENT_H__
#include <WinSock2.h>
#include <Windows.h>
#pragma comment (lib, "WS2_32.lib")
// tcp客户端
class LwTcpClient
{
private:
SOCKET _socket; // 客户端socket
char* _serverIp; // ip
int _serverPort; //端口
public:
LwTcpClient(char* serverIp, int serverPort);
~LwTcpClient();
bool Connect(); // 连接服务器
int Send(char* data, int len); // 发送数据
int Recv(char* data, int len); // 接收数据
};
#endif // !__LW_TCPCLIENT_H_
LwTcpClient.cpp
[C++] 纯文本查看 复制代码 #include "LwTcpClient.h"
#include "LwNetworkInterface.h"
LwTcpClient::LwTcpClient(char* serverIp, int serverPort)
{
LwNetworkInterface::InitWinsock();
this->_socket = socket(AF_INET, SOCK_STREAM, 0);
this->_serverIp = serverIp;
this->_serverPort = serverPort;
}
LwTcpClient::~LwTcpClient()
{
if (this->_socket != INVALID_SOCKET)
{
::closesocket(this->_socket);
}
LwNetworkInterface::ClearWinsock();
}
bool LwTcpClient::Connect()
{
sockaddr_in serverAddr = LwNetworkInterface::CreateSocketAddr(this->_serverIp, this->_serverPort);
return ::connect(this->_socket, (sockaddr *)&serverAddr, sizeof(serverAddr)) != SOCKET_ERROR;
}
int LwTcpClient::Send(char* data, int len)
{
return ::send(this->_socket, data, len, 0);
}
int LwTcpClient::Recv(char* data, int len)
{
return ::recv(this->_socket, data, len, 0);
}
-------以上代码都经过测试, 校验-------
|
免费评分
-
查看全部评分
|