mirror of
https://github.com/Kiritow/GSock.git
synced 2024-03-22 13:10:51 +08:00
Support non-blocking send and recv
This commit is contained in:
parent
34ab73a7c4
commit
6c46214f6b
224
gsock.cpp
224
gsock.cpp
|
@ -129,6 +129,7 @@ enum gerrno
|
||||||
InProgress,
|
InProgress,
|
||||||
Already,
|
Already,
|
||||||
IsConnected,
|
IsConnected,
|
||||||
|
Interrupted,
|
||||||
};
|
};
|
||||||
|
|
||||||
gerrno TranslateNativeErrToGErr(int native_errcode)
|
gerrno TranslateNativeErrToGErr(int native_errcode)
|
||||||
|
@ -144,7 +145,10 @@ gerrno TranslateNativeErrToGErr(int native_errcode)
|
||||||
return gerrno::Already;
|
return gerrno::Already;
|
||||||
case WSAEISCONN:
|
case WSAEISCONN:
|
||||||
return gerrno::IsConnected;
|
return gerrno::IsConnected;
|
||||||
|
case WSAEINTR:
|
||||||
|
return gerrno::Interrupted;
|
||||||
#else
|
#else
|
||||||
|
case EAGAIN:
|
||||||
case EWOULDBLOCK:
|
case EWOULDBLOCK:
|
||||||
return gerrno::WouldBlock;
|
return gerrno::WouldBlock;
|
||||||
case EINPROGRESS:
|
case EINPROGRESS:
|
||||||
|
@ -153,6 +157,8 @@ gerrno TranslateNativeErrToGErr(int native_errcode)
|
||||||
return gerrno::Already;
|
return gerrno::Already;
|
||||||
case EISCONN:
|
case EISCONN:
|
||||||
return gerrno::IsConnected;
|
return gerrno::IsConnected;
|
||||||
|
case EINTR:
|
||||||
|
return gerrno::Interrupted;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
myliblog("Unknown Error Code: %d\n", native_errcode);
|
myliblog("Unknown Error Code: %d\n", native_errcode);
|
||||||
|
@ -393,9 +399,11 @@ void NBConnectResult::_impl::update()
|
||||||
{
|
{
|
||||||
status = 2;
|
status = 2;
|
||||||
}
|
}
|
||||||
else
|
else // ret == -1
|
||||||
{
|
{
|
||||||
gerrno err = TranslateNativeErrToGErr(GetNativeErrCode());
|
gerrno err = TranslateNativeErrToGErr(GetNativeErrCode());
|
||||||
|
errcode = err;
|
||||||
|
|
||||||
if (err == gerrno::InProgress || err == gerrno::WouldBlock || err == gerrno::Already)
|
if (err == gerrno::InProgress || err == gerrno::WouldBlock || err == gerrno::Already)
|
||||||
{
|
{
|
||||||
status = 1;
|
status = 1;
|
||||||
|
@ -410,7 +418,7 @@ void NBConnectResult::_impl::update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
myliblog("Status updated to %d\n", status);
|
myliblog("NBConnectResult Status updated to %d\n", status);
|
||||||
}
|
}
|
||||||
|
|
||||||
NBConnectResult::NBConnectResult() : _p(new _impl)
|
NBConnectResult::NBConnectResult() : _p(new _impl)
|
||||||
|
@ -426,7 +434,6 @@ bool NBConnectResult::isFinished()
|
||||||
|
|
||||||
bool NBConnectResult::isConnected()
|
bool NBConnectResult::isConnected()
|
||||||
{
|
{
|
||||||
_p->update();
|
|
||||||
return (_p->status == 2);
|
return (_p->status == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,19 +447,195 @@ void NBConnectResult::wait()
|
||||||
while (!isFinished());
|
while (!isFinished());
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NBTransferResult::_impl
|
struct NBSendResult::_impl
|
||||||
{
|
{
|
||||||
int sfd;
|
int sfd;
|
||||||
void* ptr;
|
const char* ptr;
|
||||||
int datasz;
|
int total;
|
||||||
|
int done;
|
||||||
|
|
||||||
|
// 0: Not started.
|
||||||
|
// 1: Data is being sent
|
||||||
|
// 2: Data sent without error.
|
||||||
|
// 3: Error occurs.
|
||||||
|
int status;
|
||||||
|
|
||||||
int errcode;
|
int errcode;
|
||||||
|
|
||||||
|
void update();
|
||||||
};
|
};
|
||||||
|
|
||||||
NBTransferResult::NBTransferResult() : _p(new _impl)
|
void NBSendResult::_impl::update()
|
||||||
{
|
{
|
||||||
|
int ret = send(sfd, ptr + done, total - done, 0);
|
||||||
|
if (ret > 0)
|
||||||
|
{
|
||||||
|
done += ret;
|
||||||
|
if (done == total)
|
||||||
|
{
|
||||||
|
status = 2;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ret == 0)
|
||||||
|
{
|
||||||
|
status = 3;
|
||||||
|
errcode = 0;
|
||||||
|
}
|
||||||
|
else // ret == -1
|
||||||
|
{
|
||||||
|
gerrno err = TranslateNativeErrToGErr(GetNativeErrCode());
|
||||||
|
errcode = err;
|
||||||
|
|
||||||
|
if (err == gerrno::WouldBlock)
|
||||||
|
{
|
||||||
|
status = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
myliblog("NBSendResult status updated to %d\n", status);
|
||||||
|
}
|
||||||
|
|
||||||
|
NBSendResult::NBSendResult() : _p(new _impl)
|
||||||
|
{
|
||||||
|
_p->status = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NBSendResult::isFinished()
|
||||||
|
{
|
||||||
|
_p->update();
|
||||||
|
return (_p->status > 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NBSendResult::wait()
|
||||||
|
{
|
||||||
|
while (!isFinished());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NBSendResult::isSuccess()
|
||||||
|
{
|
||||||
|
return (_p->status == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int NBSendResult::getBytesDone()
|
||||||
|
{
|
||||||
|
return _p->done;
|
||||||
|
}
|
||||||
|
|
||||||
|
int NBSendResult::getErrCode()
|
||||||
|
{
|
||||||
|
return _p->errcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NBRecvResult::_impl
|
||||||
|
{
|
||||||
|
int sfd;
|
||||||
|
char* ptr;
|
||||||
|
int maxsz;
|
||||||
|
int done;
|
||||||
|
|
||||||
|
// When work together with epoll at ET mode, setting this flag can avoid infinite EAGAIN recv loop.
|
||||||
|
bool stopAtEdge;
|
||||||
|
|
||||||
|
// 0: Not started.
|
||||||
|
// 1: Data is being sent
|
||||||
|
// 2: Data sent without error.
|
||||||
|
// 3: Error occurs.
|
||||||
|
int status;
|
||||||
|
|
||||||
|
int errcode;
|
||||||
|
|
||||||
|
void update();
|
||||||
|
};
|
||||||
|
|
||||||
|
void NBRecvResult::_impl::update()
|
||||||
|
{
|
||||||
|
int ret = recv(sfd, ptr + done, maxsz - done, 0);
|
||||||
|
if (ret > 0)
|
||||||
|
{
|
||||||
|
done += ret;
|
||||||
|
if (done == maxsz)
|
||||||
|
{
|
||||||
|
status = 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ret == 0)
|
||||||
|
{
|
||||||
|
status = 3;
|
||||||
|
errcode = 0;
|
||||||
|
}
|
||||||
|
else // ret == -1
|
||||||
|
{
|
||||||
|
gerrno err = TranslateNativeErrToGErr(GetNativeErrCode());
|
||||||
|
errcode = err;
|
||||||
|
|
||||||
|
if (err == gerrno::WouldBlock)
|
||||||
|
{
|
||||||
|
if (stopAtEdge)
|
||||||
|
{
|
||||||
|
status = 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
myliblog("NBRecvResult status updated to %d\n", status);
|
||||||
|
}
|
||||||
|
|
||||||
|
NBRecvResult::NBRecvResult() : _p(new _impl)
|
||||||
|
{
|
||||||
|
_p->status = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NBRecvResult::setStopAtEdge(bool flag)
|
||||||
|
{
|
||||||
|
_p->stopAtEdge = flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NBRecvResult::isFinished()
|
||||||
|
{
|
||||||
|
_p->update();
|
||||||
|
return (_p->status > 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NBRecvResult::wait()
|
||||||
|
{
|
||||||
|
while (!isFinished());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NBRecvResult::isSuccess()
|
||||||
|
{
|
||||||
|
return (_p->status == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int NBRecvResult::getBytesDone()
|
||||||
|
{
|
||||||
|
return _p->done;
|
||||||
|
}
|
||||||
|
|
||||||
|
int NBRecvResult::getErrCode()
|
||||||
|
{
|
||||||
|
return _p->errcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NBConnectResult sock::connect_nb(const std::string& IPStr, int Port)
|
NBConnectResult sock::connect_nb(const std::string& IPStr, int Port)
|
||||||
{
|
{
|
||||||
|
@ -523,6 +706,31 @@ int sock::recv(void* Buffer,int MaxToRecv)
|
||||||
return ::recv(_vp->sfd,(char*)Buffer,MaxToRecv,0);
|
return ::recv(_vp->sfd,(char*)Buffer,MaxToRecv,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NBSendResult sock::send_nb(const void* Buffer, int Length)
|
||||||
|
{
|
||||||
|
NBSendResult res;
|
||||||
|
res._p->ptr = (const char*)Buffer;
|
||||||
|
res._p->total = Length;
|
||||||
|
res._p->done = 0;
|
||||||
|
res._p->sfd = _vp->sfd;
|
||||||
|
|
||||||
|
res._p->update();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
NBRecvResult sock::recv_nb(void* Buffer, int MaxToRecv)
|
||||||
|
{
|
||||||
|
NBRecvResult res;
|
||||||
|
res._p->ptr = (char*)Buffer;
|
||||||
|
res._p->maxsz = MaxToRecv;
|
||||||
|
res._p->done = 0;
|
||||||
|
res._p->stopAtEdge = false;
|
||||||
|
res._p->sfd = _vp->sfd;
|
||||||
|
|
||||||
|
res._p->update();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
int sock::getsendtime(int& _out_Second, int& _out_uSecond)
|
int sock::getsendtime(int& _out_Second, int& _out_uSecond)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
33
gsock.h
33
gsock.h
|
@ -71,12 +71,37 @@ private:
|
||||||
friend class sock;
|
friend class sock;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NBTransferResult
|
class NBSendResult
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NBTransferResult();
|
NBSendResult();
|
||||||
|
|
||||||
|
// Is the operation finished.
|
||||||
|
bool isFinished();
|
||||||
|
// Wait until all data is sent.
|
||||||
|
void wait();
|
||||||
|
// Is all data sent successfully.
|
||||||
|
bool isSuccess();
|
||||||
|
int getBytesDone();
|
||||||
|
|
||||||
|
int getErrCode();
|
||||||
|
private:
|
||||||
|
struct _impl;
|
||||||
|
std::shared_ptr<_impl> _p;
|
||||||
|
|
||||||
|
friend class sock;
|
||||||
|
};
|
||||||
|
|
||||||
|
class NBRecvResult
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NBRecvResult();
|
||||||
|
|
||||||
|
void setStopAtEdge(bool flag);
|
||||||
|
|
||||||
bool isFinished();
|
bool isFinished();
|
||||||
|
void wait();
|
||||||
|
bool isSuccess();
|
||||||
int getBytesDone();
|
int getBytesDone();
|
||||||
|
|
||||||
int getErrCode();
|
int getErrCode();
|
||||||
|
@ -104,8 +129,8 @@ public:
|
||||||
// return what send() and recv() call returns.
|
// return what send() and recv() call returns.
|
||||||
int send(const void* Buffer,int Length);
|
int send(const void* Buffer,int Length);
|
||||||
int recv(void* Buffer, int MaxToRecv);
|
int recv(void* Buffer, int MaxToRecv);
|
||||||
NBTransferResult send_nb(const void* Buffer, int Length);
|
NBSendResult send_nb(const void* Buffer, int Length);
|
||||||
NBTransferResult recv_nb(void* Buffer, int MaxToRecv);
|
NBRecvResult recv_nb(void* Buffer, int MaxToRecv);
|
||||||
|
|
||||||
// Return:
|
// Return:
|
||||||
// GSOCK_OK
|
// GSOCK_OK
|
||||||
|
|
Loading…
Reference in New Issue
Block a user