今天继续深入学习socket套接字的使用,上一篇文章我们主要深入介绍了如何使用套接字进行面向连接的通信编程,这里我们主要深入讲解一下基于面向非连接的编程。
对于TCP面向连接来说,在通信前,需要经过三步握手协议以建立连接,而建立连接的过程往往比较耗费时间。连接建立后,在聊天过程中,可能经过好吃一段时间,聊天的双方才会说一句话(网速比较慢的情况比较常见),那么连接是一个保存还是应先断开,等对方说话时再建立连接呢?也就是说,TCP协议的面向连接、数据确认和重传机制将会影响聊天的效率。所以我们就有必要引入另一种协议来填充这个不足缺口。目前通常采用基于UDP非连接的方式来实现。这种方式的特点是不需要建立连接,也没有数据确认和重传机制,因此实时性较高。
下面我们列举一个基于UDP的聊天列举编程进行深入透析:
- 服务器端代码:
1 #include<Winsock2.h> 2 #include<stdio.h> 3 4 void main() 5 { 6 //load socket libariy 7 WORD wVersionRequested; 8 //this struct use to stored Windows Sockets value after call WSAStartup() function, 9 //include the data from Winscok.dll 10 WSADATA wsaData; 11 int err; 12 wVersionRequested=MAKEWORD(1,1); 13 err = WSAStartup(wVersionRequested,&wsaData); 14 if(err!=0) 15 { 16 return; 17 } 18 if(LOBYTE(wsaData.wVersion)!=1 || (HIBYTE(wsaData.wVersion)!=1)) 19 { 20 WSACleanup(); 21 return; 22 } 23 //create socket--- Protocol udp 24 SOCKET sockSrv=socket(AF_INET,SOCK_DGRAM,0); 25 //Setup socket address information 26 SOCKADDR_IN addrSrv; 27 addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY); 28 addrSrv.sin_family=AF_INET; 29 addrSrv.sin_port=htons(6000); 30 //binding socket with its address and port 31 if(bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR))==0) 32 { 33 printf("Server start...OK! "); 34 //data buffer; 35 char recvBuf[100]; 36 char sendBuf[100]; 37 char tempBuf[200]; 38 //client address information 39 SOCKADDR_IN addrClient; 40 int len=sizeof(SOCKADDR); 41 //endless: to receive client data 42 while(1) 43 { 44 //wait data incomming 45 recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&len); 46 //only receive 'q' or 'Q', stop. 47 if(('q'==recvBuf[0])||('Q')==recvBuf[0]) 48 { 49 if(strlen(recvBuf)==1) 50 { 51 //chat end 52 sendto(sockSrv,"q",strlen("q")+1,0,(SOCKADDR*)&addrClient,len); 53 printf("Chat end! "); 54 break; 55 } 56 } 57 //printf receive information 58 sprintf(tempBuf,"%s: %s",inet_ntoa(addrClient.sin_addr),recvBuf); 59 printf("%s server:",tempBuf); 60 //get input message 61 gets(sendBuf); 62 sendto(sockSrv,sendBuf,strlen(sendBuf)+1,0,(SOCKADDR*)&addrClient,len); 63 } 64 } 65 else 66 { 67 printf("Server failed start. "); 68 } 69 //close socket 70 closesocket(sockSrv); 71 WSACleanup(); 72 }
- 客户端代码:
1 #include<Winsock2.h> 2 #include<stdio.h> 3 4 void main() 5 { 6 //load socket libariy 7 WORD wVersionRequested; 8 //this struct use to stored Windows Sockets value after call WSAStartup() function, 9 //include the data from Winscok.dll 10 WSADATA wsaData; 11 int err; 12 wVersionRequested=MAKEWORD(1,1); 13 err = WSAStartup(wVersionRequested,&wsaData); 14 if(err!=0) 15 { 16 return; 17 } 18 if(LOBYTE(wsaData.wVersion)!=1 || (HIBYTE(wsaData.wVersion)!=1)) 19 { 20 WSACleanup(); 21 return; 22 } 23 //create socket--- Protocol udp 24 SOCKET sockClient=socket(AF_INET,SOCK_DGRAM,0); 25 printf("Client create....OK! "); 26 //define variable for server address information struct 27 SOCKADDR_IN addrSrv; 28 addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); 29 addrSrv.sin_family=AF_INET; 30 addrSrv.sin_port=htons(6000); 31 //data buffer 32 char recvBuf[100]; 33 char sendBuf[100]; 34 char tempBuf[200]; 35 int len=sizeof(SOCKADDR); 36 //endless 37 while(1) 38 { 39 printf("Client: "); 40 gets(sendBuf); 41 sendto(sockClient,sendBuf,strlen(sendBuf)+1,0,(SOCKADDR*)&addrSrv,len); 42 //wait response from server 43 recvfrom(sockClient,recvBuf,100,0,(SOCKADDR*)&addrSrv,&len); 44 if(strlen(recvBuf)==1) 45 { 46 if(recvBuf[0]=='q') 47 { 48 printf("chat end. "); 49 break; 50 } 51 } 52 sprintf(tempBuf,"%s: %s",inet_ntoa(addrSrv.sin_addr),recvBuf); 53 printf("%s ",tempBuf); 54 } 55 closesocket(sockClient); 56 WSACleanup(); 57 }
- 程序的开头,都是需要加载套接字库。因为通信是基于UDP协议的,所以加载数据报类型的套接字(SOCK_DGRAM)。之后需要定义一个地址类型(SOCKADDR_IN)变量,用来接收返回的套接字参数。
- 编译运行:
End.
谢谢.