对于客户端Client来说,建立模型的步骤:
1、装入并初始化相关dll库:
if(WSAStartup(0x101,&lpWSAData)!=0){
MessageBox(NULL,"装入并初始化DLL库失败",NULL,MB_OK);
}
2、创建套接字:
if((hSocket=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET){
WSAGetLastError();
MessageBox(NULL,"创建套接字失败",NULL,MB_OK);
return FALSE;
}
注意其中if语句中的判断顺序,先有socket()函数的赋值到hSocket中,再有hSocket==INVALID_SOCKET,注意括号的使用,否则总是得到hSocket=INVALID_SOCKET;
3、设置套接字的工作模式:
以上的创建的套接字默认情况下实在阻塞模式下工作的,为了适应windows程序工作的特点(是以消息机制来进行一系列的相关处理),要将其设置为非阻塞的工作模式:
WSAAsyncSelect(hSocket,hWnd,WM_SOCKET,FD_CONNECT|FD_READ|FD_CLOSE|FD_WRITE);
其中WM_SOCKET是自定义消息,当调用完这个函数后,此消息便会和以hWnd为句柄的窗口绑定,当发生相应事件时,便一此消息的低双字节的lParam来指定通知码(FD_CONNET,FD_CLOSE或FD_WEITE);
4、连接到服务器:
int i=connect(hSocket,(struct sockaddr *)&stSin,sizeof(struct sockaddr));//将套接字绑定到IP地址和端口
其中结构变量stSin是一个sockaddr_in类型的结构体变量:
stSin.sin_addr.s_addr=inet_addr(szBuffers);//指定IP地址,其中inet_addr()函数将小数点分隔的IP地址字符串转换为32位二进制表示的IP地址(网络字节顺序)
stSin.sin_family=AF_INET; //指定地址格式
stSin.sin_port= htons(TCP_PORT);//指定端口号,htons()函数将但前主机字节顺序排列的数据转换成按网络顺序排列的数据:
注意此时当发生这个连接动作后,服务器端的窗口程序将会接收到FD_ACCEPT的通知码,
(到这里也就顺便写到服务器端的模型建立:
1、也是装入并初始化相关dll库;
2、创建“监听套接字”hSocket
3、设置工作模式为非阻塞模式:
WSAAsyncSelect(hSocket,hWnd,WM_SOCKET,FD_ACCEPT|FD_READ|FD_CLOSE);
4、将新的套接字与自身的IP地址和端口绑定:
int result=bind(hSocket,(struct sockaddr *)&stSin,sizeof(stSin));
5、监听这个套接字:
if(listen(hSocket,5)==SOCKET_ERROR)
MessageBox(NULL,"监听失败",NULL,MB_OK);
)
stSin.sin_addr.s_addr=dwIpAddr;
stSin.sin_family=AF_INET;
u_short ax=htons(TCP_PORT);//
stSin.sin_port= ax;
int i=connect(hSocket,(struct sockaddr *)&stSin,sizeof(struct sockaddr));
int i=connect(hSocket,(struct sockaddr *)&stSin,sizeof(struct sockaddr));
当服务器端监听到有客户端发送了连接请求,则在监听套接字的作用下,服务器端的消息机制发生FD_ACCEPT的通知码,来接收客户端的请求:
if((hNewSocket=accept(wParam,0,0))==INVALID_SOCKET){
MessageBox(NULL,"接受客户端连接请求失败",NULL,MB_OK);
break;
}
注意此时返回的套接字不是之前的那个“监听套接字”了,这个套接字是和客户端相连的,而和客户端进行通信而使用的recv和send都是针对此套接字;
5、向服务其端发送消息:
send(hSocket,szBuffer,strlen,0);
此时服务器端将发生FD_READ的通知码,并可调用recv()函数获得客户端的文本内容:
recv(_hSocket,szReadBuffer,sizeof(szReadBuffer),NULL);
此时服务器端可以以自己的文本格式向客户端发送文本消息:
send(hSocket,szBuffer,strlen,0);
注意:其中_hSocket就是客户端与服务器端相连时所用到的套接字,在FD_READ的wParam变量中便保存着此值。
6、获得有服务器端发送过来的文本请求:
同服务器端相同,在FD_READ通知码中调用recv()接收服务器端的文本格式内容‘
7、相关收尾工作,套接字的关闭,相关dll库的释放:
closesocket(hSocket);
WSACleanup();
WSACleanup();