基于TCP的协议通信双方为服务器和客户端,服务器为客户端提供服务。程序需要头文件winsock2.h以及ws2_32.lib。在main函数中需先执行Windows套接字的启动命令,即WSAStartup。此函数的具体使用方法见MSDN。
服务器与客户端的通信过程中:
1.服务器执行的功能分别为:
创建SOCKET->bind(将套接字绑定到一个本地地址和端口上)->LISTEN->ACCEPT->send/recv->wait->close.其中bind函数需要一类型为SOCKADDR*的参数,本参数可由另一结构体代替(SOCKADDR_IN),在本结构体中需初始化的参数有sin_family,sin_port以及另一个结构体sin_addr。
代码:
addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000);
绑定完成后调用listen函数。之后进入while(1)的死循环,调用accept等函数
2.客户端执行的功能分别为:
SOCKET->connect->recv/send。注意:addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
在connect函数中的参数addrSrv的IP应指定,
并在最后closeSocket&&WSACleanup()
Service:
#include
#include
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested,
&wsaData );
if ( err != 0 )
return;
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 )
{
WSACleanup( );
return;
}
SOCKET
sockSrv=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN sockaddr;
sockaddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
sockaddr.sin_family=AF_INET;
sockaddr.sin_port=htons(6000);
bind(sockSrv,(SOCKADDR*)&sockaddr,sizeof(SOCKADDR));
listen(sockSrv,5);
SOCKADDR_IN addrClient;
int len=sizeof(SOCKADDR);
while(1)
{
SOCKET
sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);
char
SendBuf[100];
//wsprintf(SendBuf,"Welcome");
//send(sockConn,SendBuf,strlen(SendBuf)+1,0);
send(sockConn,SendBuf,wsprintf(SendBuf,"Welcome")+1,0);
char
recvBuf[100];
recv(sockConn,recvBuf,100,0);
printf("%s\n",recvBuf);
closesocket(sockConn);
}
}
Client:
#include
#include
void main()
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested,
&wsaData );
if ( err != 0 )
return;
if ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 )
{
WSACleanup( );
return;
}
SOCKET
sockClient=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN sockaddr;
sockaddr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
sockaddr.sin_family=AF_INET;
sockaddr.sin_port=htons(6000);
connect(sockClient,(SOCKADDR*)&sockaddr,sizeof(SOCKADDR));
char
recvBuf[100],sendBuf[100];
recv(sockClient,recvBuf,100,0);
printf("%s\n",recvBuf);
send(sockClient,sendBuf,wsprintf(sendBuf,"thanks,i'm
client")+1,0);
closesocket(sockClient);
WSACleanup();
}
基于UDP的协议:
服务器流程为socket->bind->recvfrom/sendto->close。不需要listen&accept
客户端流程为socke->recvfrom/sendto->close。不需要connect
注意bind和recvfrom/sento中SOCKADDR的区别:bind为绑定,其中SOCKADDR由用户初始化。recvfrom/sendto中的SOCKADDR为out,即在函数执行后由系统赋值