winSockets编程(四)阻塞模式(服务端)
标签:变量 mil cti 编程 strcpy any ide logs style
在阻塞模式下,在I/O操作完成前,执行的操作函数将一直等候而不会立即返回,该函数所在的线程会阻塞在这里。相反,在非阻塞模式下,套接字函数立即返回,而不管I/O是否完成。
#生产者和消费者模式
##
服务器端的简化形式(#这套流程需要完全背诵#)
/*****************初始化***********************/
int retVal;
WSAData wsd;
retVal = WSAStartup(MAKEWORD(1, 1), &wsd);
/****************************************/
//创建套接字
sSever = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
/************绑定套接字****************************/
SOCKADDR_IN addrServ;
addrServ.sin_family = AF_INET;
addrServ.sin_port = htons(5999);
addrServ.sin_addr.s_addr = INADDR_ANY;
retVal = bind(sSever, (LPSOCKADDR)&addrServ, sizeof(SOCKADDR_IN));
/****************************************/
//监听
retVal = listen(sSever, 1);
/***************获取客户端请求,线程在阻塞************************/
SOCKADDR_IN addrClient;
int addrClientlen = sizeof(addrClient);
sClient = accept(sSever, (sockaddr FAR*)&addrClient, &addrClientlen);
/***************************************/
while (true) //从接收缓冲区中读取数据,每次一个字节;
{
nReadLen = recv(s, buf + nDataLen, 1, 0);
........
}
retVal = send(s, str, strlen(str), 0); //发送数据(一次发送)
#完整代码#
#include
#include #pragma comment(lib, "wsock32.lib")
#define SERVER_EXIT_OK 0 //服务器正常退出;
#define SERVER_DLL_REEOR 1 //调用Windows sockets DLL失败;
#define SERVER_API_ERROR 2 //调用Windows sockets API失败;
#define SERVERPORT 5555 //服务器TCP端口;
char bufRecv[MAX_PATH]; //读缓冲区;
char bufSend[MAX_PATH]; //写缓冲区;
SOCKET sServer; //服务器监听套接字;
SOCKET sClient; //接受客户端套接字;
BOOL bConning; //与客户端的连接状态;
void InitMember(void); //初始化成员变量;
int ExitClient(int nExit); //客户端退出;
BOOL RecvLine(SOCKET s, char* buf); //读取一行数据;
BOOL SendLine(SOCKET s, char* buf); //发送一行数据;
int HandleSocketError(char *str); //对Windows sockets API调用错误处理;
void ShowSocketMsg(char* str); //显示错误信息;
int main(int argc, char* argv[])
{
InitMember();
WSADATA wsaData; //Windows sockets DLL版本信息
int retVal; //调用Windows sockets API返回值
retVal = WSAStartup(MAKEWORD(1, 1), &wsaData);
if (0 != retVal)
{
ShowSocketMsg("找不到可用的Socket DLL!");
return SERVER_DLL_REEOR;
}
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
{
ShowSocketMsg("Can not find a usable Windows Sockets dll!");
WSACleanup();
return SERVER_DLL_REEOR;
}
//创建套接字;
/*******************************************************/
sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == sServer)
{
return HandleSocketError("Failed socket()!");
}
/********************************************************/
//服务器套接字地址;
SOCKADDR_IN addrServ;
addrServ.sin_family = AF_INET;
addrServ.sin_port = htons(SERVERPORT);
addrServ.sin_addr.s_addr = INADDR_ANY;
retVal = bind(sServer, (LPSOCKADDR)&addrServ, sizeof(SOCKADDR_IN));//绑定套接字;
if (SOCKET_ERROR == retVal)
{
closesocket(sServer);
return HandleSocketError("Failed bind()!");
}
retVal = listen(sServer, 1);//开始监听;
if (SOCKET_ERROR == retVal)
{
closesocket(sServer);
return HandleSocketError("Failed listen()!");
}
std::cout "Server succeeded!" //等待客户端的连接;
std::cout "Waiting for new clients..." std::endl;
/***********接受客户端请求****************************/
sockaddr_in addrClient;
int addrClientlen = sizeof(addrClient);
sClient = accept(sServer, (sockaddr FAR*)&addrClient, &addrClientlen);
if (INVALID_SOCKET == sClient)
{
closesocket(sServer);
return HandleSocketError("Failed accept()!");
}
else
{
bConning = TRUE;//客户端请求成功;
}
//显示客户端的IP和端口;
char *pClientIP = inet_ntoa(addrClient.sin_addr);
u_short clientPort = ntohs(addrClient.sin_port);
std::cout "Accept a client." std::endl;
std::cout "IP: " std::endl;
std::cout "Port: " std::endl;
if (!RecvLine(sClient, bufRecv))//接收客户端数据;
{
return ExitClient(SERVER_API_ERROR);
}
std::cout //显示客户端数据;
strcpy_s(bufSend, "Hello,Client!\n");//向客户端发送数据;
if (!SendLine(sClient, bufSend))
{
return ExitClient(SERVER_API_ERROR);
}
std::cout "Server exiting..." //显示退出信息;
return ExitClient(SERVER_EXIT_OK);
}
void InitMember(void)
{
memset(bufRecv, 0, MAX_PATH);
memset(bufSend, 0, MAX_PATH);
sServer = INVALID_SOCKET;
sClient = INVALID_SOCKET;
bConning = FALSE;
}
int ExitClient(int nExit)
{
closesocket(sServer);
closesocket(sClient);
WSACleanup();
return nExit;
}
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;
}
BOOL SendLine(SOCKET s, char* str)
{
int retVal;//返回值
retVal = send(s, str, strlen(str), 0);//一次发送
//错误处理
if (SOCKET_ERROR == retVal)
{
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
{
}
return FALSE; //发送失败
}
return TRUE; //发送成功
}
int HandleSocketError(char *str)
{
ShowSocketMsg(str); //显示错误消息
WSACleanup(); //卸载Windows socket DLL
return SERVER_API_ERROR;//退出应用程序
}
void ShowSocketMsg(char* str)
{
MessageBox(NULL, str, "SERVER ERROR", MB_OK);
}
winSockets编程(四)阻塞模式(服务端)
标签:变量 mil cti 编程 strcpy any ide logs style
原文地址:http://www.cnblogs.com/tinaluo/p/7691363.html
评论