将 winsock 封装成一个类但 Recv 函数中出现了问题
下面是问题代码:
std::string recvBuf;
char buffer[10240];
int flags = 1;
int forn = 12;
if (isBlocking)
{
flags = 0;
forn = 1;
}
recvBuf.clear();
ioctlsocket(s1, FIONBIO, (unsigned long *)&flags);
for (int i = 1; i <= forn; i++)
{
while (recv(s1, buffer, 1, 0) > 0)
{
recvBuf += buffer;
}
Sleep(1);
}
flags = 0;
ioctlsocket(s1, FIONBIO, (unsigned long *)&flags);
问题是它运行后不返回
完整代码:
#include <winsock2.h>
#include <windows.h>
#include <string>
#include <cstring>
#define default_sock 0
#pragma comment(lib, "WS2_32.lib")
class socks
{
private:
int is_server;
int flag;
std::string ip;
int port;
SOCKET s1;
sockaddr_in addr;
public:
socks()
{
port = 80;
is_server = 0;
flag = 0;
};
~socks() { WSACleanup(); };
socks(std::string addrr /*ip 地址*/, int port = 80 /*端口号(默认 80 端口)*/)
{
init(port, addrr);
this->port = port;
this->ip = addrr;
is_server = 0;
flag = 0;
}
/*
-----
功能:初始化套接字
```C++
int port:端口号
string addrr:ip 地址
return:bool:是否成功(true:成功 false:失败)
```
*/
bool init(int port, std::string addrr)
{
WSADATA data;
WORD w = MAKEWORD(2, 1);
if (::WSAStartup(w, &data) != 0)
return false;
s1 = ::socket(AF_INET, SOCK_STREAM, 0);
if (s1 == INVALID_SOCKET)
return false;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.S_un.S_addr = inet_addr(addrr.c_str());
flag = 1;
this->port = port;
this->ip = addrr;
return true;
}
/*
-----
功能:绑定地址并监听(服务器)
```C++
int listens:同时监听几个连接
return:bool:是否成功(true:成功 false:失败)
```
*/
bool Bind(int listens)
{
if (flag == 1 && is_server == 0)
{
if (bind(s1, (SOCKADDR *)&addr, sizeof(SOCKADDR)) != 0)
return false;
if (listen(s1, listens) != 0)
return false;
flag = 2;
is_server = 2;
return true;
}
return false;
}
/*
-----
功能:接受连接(服务器)
```C++
bool isBlocking:是否堵塞并等待连接(true:表示堵塞 false:表示不堵塞)
return SOCKET:返回套接字(NULL:表示无连接或错误)
```
*/
SOCKET Accept(bool isBlocking = true)
{
if (flag == 2 && is_server == 2)
{
int flag = 0;
if (!isBlocking)
flag = 1;
ioctlsocket(s1, FIONBIO, (unsigned long *)&flag);
sockaddr_in accepts;
int accept_len = sizeof(accepts);
SOCKET status = accept(s1, (struct sockaddr *)&accepts, &accept_len);
flag = 0;
ioctlsocket(s1, FIONBIO, (unsigned long *)&flag);
if (status == INVALID_SOCKET)
{
return NULL;
}
return status;
}
return NULL;
}
/*
-----
功能:连接服务器(客户端)
```C++
return bool:是否连接成功(true:表示连接成功 false:表示连接失败)
```
*/
bool Connect()
{
if (is_server == 0 && flag == 1)
{
int status = connect(s1, (sockaddr *)&addr, sizeof(sockaddr));
if (status == INVALID_SOCKET)
{
return false;
}
flag = 2;
return true;
}
return false;
}
/*
-----
功能:发送消息
```C++
string sendBuf:发送的消息
SOCKET SendSock:发送消息的套接字
return:bool:是否成功(true:成功 false:失败)
```
*/
bool Send(std::string sendBuf, SOCKET SendSock = default_sock)
{
if (SendSock == default_sock && flag == 2 && is_server == 0)
{
send(s1, sendBuf.c_str(), sendBuf.length(), 0);
return true;
}
else if (SendSock != default_sock && flag == 2)
{
send(SendSock, sendBuf.c_str(), sendBuf.length(), 0);
return true;
}
else
return false;
}
/*
-----
功能:接受消息
```C++
SOCKET RecvSock:接受消息的套接字
bool isBlocking:是否堵塞接收(true:表示堵塞接收 false:表示非堵塞接收)
return:string 接收到的消息(返回空字符串表示失败)
```
*/
std::string Recv(SOCKET RecvSock = default_sock, bool isBlocking = false)
{
if (RecvSock == default_sock && flag == 2 && is_server == 0)
{
std::string recvBuf;
char buffer[10240];
int flags = 1;
int forn = 12;
if (isBlocking)
{
flags = 0;
forn = 1;
}
recvBuf.clear();
ioctlsocket(s1, FIONBIO, (unsigned long *)&flags);
for (int i = 1; i <= forn; i++)
{
while (recv(s1, buffer, 1, 0) > 0)
{
recvBuf += buffer;
}
Sleep(1);
}
flags = 0;
ioctlsocket(s1, FIONBIO, (unsigned long *)&flags);
return recvBuf;
}
else if (RecvSock != default_sock && flag == 2)
{
std::string recvBuf;
char buffer[1024];
int close_recv = 0;
int forn = 12;
int flags = 1;
if (isBlocking)
{
flags = 0;
forn = 1;
}
recvBuf.clear();
ioctlsocket(RecvSock, FIONBIO, (unsigned long *)&flags);
for (int i = 1; i <= forn; i++)
{
while (recv(RecvSock, buffer, 1, 0) > 0)
{
recvBuf += buffer;
}
Sleep(1);
}
flags = 0;
ioctlsocket(RecvSock, FIONBIO, (unsigned long *)&flags);
return recvBuf;
}
else
{
return "";
}
}
/*
-----
功能:释放套接字
```C++
return:void:无返回
```
*/
void Close()
{
closesocket(s1);
flag = 0;
}
/*
-----
功能:设置端口
```C++
int port:要设置的端口
return:bool:是否成功(true:成功 false:失败)
```
*/
bool SetPort(int port)
{
if (flag == 0)
{
addr.sin_port = htons(port);
this->port = port;
return true;
}
else
return false;
}
/*
-----
功能:设置ip地址
```C++
string ip:要设置的 ip 地址
return:bool:是否成功(true:成功 false:失败)
```
*/
bool SetIp(std::string ip)
{
if (flag == 0)
{
addr.sin_addr.S_un.S_addr = inet_addr(ip.c_str());
this->ip = ip;
return true;
}
else
return false;
}
/*
-----
功能:获取端口
```C++
return:int:端口号
```
*/
int getPort() { return this->port; }
/*
-----
功能:获取 ip
```C++
return:string:ip
```
*/
std::string getIp() { return this->ip; }
/*
-----
功能:获取错误号
```C++
return:int:错误号
```
*/
int getError() { return WSAGetLastError(); }
};