1.初始化与绑定服务器
WSADATA wsadata;
if (WSAStartup(MAKEWORD(2, 1), &wsaData)) //调用Windows Sockets DLL
{
error = _T("winSock 初始化失败");
WSACleanup();
return FALSE;
}
头文件 header: Winsock2.h
库library: Ws2_32.lib
原型:int PASCAL FAR WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData );
参数:(1).wVersionRequested是Windows Sockets API提供的调用方可使用的最高版本号。高位字节指出副版本(修正)号,低位字节指明主版本号。
(2).lpWSAData 是指向WSADATA数据结构的指针,用来接收Windows Sockets实现的细节。
2.开始创建服务器socket
ServerSocket = socket(PF_INET,SOCK_STREAM,0);
if (ServerSocket == INVALID_SOCKET)
{
error = _T("无法创建服务器socket!");
return FALSE;
}
int socket( int af, int type, int protocol);
af:一个地址描述。仅支持AF_INET格式,也就是说ARPA Internet地址格式。
type:指定socket类型。新套接口的类型描述类型,如TCP(SOCK_STREAM)和UDP(SOCK_DGRAM)。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等。
protocol:顾名思义,就是指定协议。套接口所用的协议。如调用者不想指定,可用0。常用的协议有,IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。
3.IP与Port设定
m_sockServerAddr.sin_family = AF_INET;
m_sockServerAddr.sin_addr.s_addr = INADDR_ANY; //向所有的IP地址发送消息
m_sockServerAddr.sin_port = htons(8222);
4.绑定服务器
if (bind(ServerSocket,(LPSOCKADDR)&m_sockServerAddr,sizeof(m_sockServerAddr)) == SOCKET_ERROR)
{
error = _T("无法绑定服务器socket!");
return FALSE;
}
int bind(int sockfd, const struct sockaddr, socklen_t addrlen);
sockaddr第二个参数是一个指向特定协议的地址结构的指针,
addrlen第三个参数是该地址结构的长度。
对于TCP,调用bind函数可以指定一个端口号,或指定一个IP地址,也可以两者都指定,还可以都不指定。
5异步编程方法
// 产生相应传递给窗口的消息为WM_SERVER_ACCEPT ,这是自定义消息
#define WM_CLIENT_ACCEPT WM_USER+101
//绑定消息
iErrorCode = WSAAsyncSelect(ServerSocket, m_hWnd, WM_CLIENT_ACCEPT, FD_ACCEPT);
if (iErrorCode == SOCKET_ERROR)
{
error = _T("WSAAsyncSelect设定失败!——用于连接请求的消息");
return FALSE;
}
消息响应
ON_MESSAGE(WM_CLIENT_ACCEPT, OnAccept)
OnAccept()函数定义在下面 --请不要急哦!
6.开始监听客户连接请求
//开始监听客户连接请求
if (listen(ServerSocket, 1) == SOCKET_ERROR)
{
list.InsertString(0, _T("服务器监听失败!"));
return FALSE;
}
7 代码函数
注意消息定义以及消息映射如下:
#define WM_CLIENT_ACCEPT WM_USER+101
ON_MESSAGE(WM_CLIENT_ACCEPT, OnAccept)
#define WM_CLIENT_READCLOSE WM_USER+102
ON_MESSAGE(WM_CLIENT_READCLOSE, OnReadClose)
BOOL CXXXDlg::CreateServer(CString &error)
{
WSADATA wsaData;
int iErrorCode;
if (WSAStartup(MAKEWORD(2, 1), &wsaData)) //调用Windows Sockets DLL
{
error = _T("winSock 初始化失败");
WSACleanup();
return FALSE;
}
OutputDebugString(_T("服务器开始创建SOCKET。"));
ServerSocket = socket(PF_INET,SOCK_STREAM,0);
if (ServerSocket == INVALID_SOCKET)
{
error = _T("无法创建服务器socket!");
return FALSE;
}
OutputDebugString(_T("服务器创建SOCKET成功。"));
m_sockServerAddr.sin_family = AF_INET;
m_sockServerAddr.sin_addr.s_addr = INADDR_ANY; //向所有的IP地址发送消息
m_sockServerAddr.sin_port = htons(8222);
if (bind(ServerSocket,(LPSOCKADDR)&m_sockServerAddr,sizeof(m_sockServerAddr)) == SOCKET_ERROR)
{
error = _T("无法绑定服务器socket!");
return FALSE;
}
OutputDebugString(_T("服务器绑定SOCKET成功。"));
iErrorCode = WSAAsyncSelect(ServerSocket, m_hWnd, WM_CLIENT_ACCEPT, FD_ACCEPT);
if (listen(ServerSocket,1) == SOCKET_ERROR)
{
error = _T("无法监听服务器socket!");
return FALSE;
}
OutputDebugString(_T("服务器监听SOCKET成功。"));
return TRUE;
}
LRESULT CXXXDlg::OnAccept(WPARAM wParam, LPARAM lParam)
{//自定义接收客户机请求的消息 ON_MESSAGE(WM_CLIENT_ACCEPT,OnAccept)
if (WSAGETSELECTERROR(lParam))
{
OutputDebugString( _T("进入accept失败"));
return 0L;
}
if (WSAGETSELECTEVENT(lParam) == FD_ACCEPT)//如果
{
Client = accept(ServerSocket, (LPSOCKADDR)&m_sockServerAddr, 0);
if (Client == INVALID_SOCKET)
{
OutputDebugString(_T("未接收到连接"));
return 0L;
}
WSAAsyncSelect(Client, m_hWnd, WM_CLIENT_READCLOSE, FD_READ | FD_CLOSE);
IsTrue = TRUE;
}
OutputDebugString(_T("有客户端连接上了服务器。"));
return 0L;
}
LRESULT CXXXDlg::OnReadClose(WPARAM wParam, LPARAM lParam)
{//自定义的关闭与缓冲区有消息
if (!IsTrue)
{
OutputDebugString( _T("有数据到达,但是没有工作站连接。"));
}
CString str;
CString Error;
Sendbuf *p_rec = NULL;
switch (WSAGETSELECTEVENT(lParam))
{
case FD_READ:
//客户端有数据会触发FD_READ消息 进行 recv()
break;
case FD_CLOSE:
OutputDebugString( _T("工作站退出。");
list.InsertString(0, str);
closesocket(Client);
IsTrue = FALSE;
break;
}
return 0;
}