recvLine()函数实现接收一行数据的功能。在该函数中定义bLineEnd变量作为一行结束的标志。该变量和bConning变量一起作为While语句循环的条件。
将recv()函数的第3个参数设置为1,使得该函数每次仅接收一个字符。通过判断接收的字符是否为'/n',来判断是否已经接收了一行数据。当接收字符为'/n'时,将bLineEnd设置为True。While语句循环结束,该函数返回True。
调用recv()函数失败时,调用break语句跳出while循环体,recvLine()函数返回值False。以该函数的返回值,判断是否成功地从客户端接收了一行数据。
当recv()函数返回值为0时,说明此时客户端的关闭了连接。
recvLine()函数程序清单如下。
/*
* 读一行数据
*/
BOOL RecvLine(SOCKET s, char* buf)
{
BOOL retVal = TRUE; //返回值
BOOL bLineEnd = FALSE; //行结束
int nReadLen = 0; //读入字节数
int nDataLen = 0; //数据长度
while (!bLineEnd && bConning) //与客户端连接 没有换行
{
nReadLen = recv(s, buf + nDataLen, 1, 0);//每次接收一个字节
//错误处理
if (SOCKET_ERROR == nReadLen)
{
int nErrCode = WSAGetLastError();//错误代码
if (WSAENOTCONN == nErrCode)
{
ShowSocketMsg("The socket is not connected!");
}else if(WSAESHUTDOWN == nErrCode)
{
ShowSocketMsg("The socket has been shut down!");
}else if (WSAETIMEDOUT == nErrCode)
{
ShowSocketMsg("The connection has been dropped!");
}else if (WSAECONNRESET == nErrCode)
{
ShowSocketMsg("The virtual circuit was reset by the remote side!");
}else{}
retVal = FALSE; //读数据失败
break; //跳出循环
}
if (0 == nReadLen) //客户端关闭
{
retVal = FALSE; //读数据失败
break ; //跳出循环
}
//读入数据
if ('/n' == *(buf + nDataLen)) //换行符
{
bLineEnd = TRUE; //接收数据结束
}else{
nDataLen += nReadLen; //增加数据长度
}
}
return retVal;
}
注意:在调用Windows Sockets API时,如果调用函数失败,大多数函数返回SOCKET_ERROR。调用者可以使用WSAGetLastError()函数,获得错误代码。WSAGetLastError()函数得到最近一次操作失败时的错误代码。在下面的示例代码中,WSAGetLastError()函数使用是不正确的。
int retVal = listen(sServer, 2);
if(SOCKET_ERROR == retVal)
{
closesocket(sServer);
int nErrCode = WSAGetLastError();
if (WSAENETDOWN == nErrCode) //错误处理
{
//处理
}
}