【windows socket+UDP服务器客户端】

UDP服务器客户端实践
本文介绍Windows环境下使用Winsock实现UDP服务器与客户端的编程方法。详细解释了UDP编程的基本函数,并通过一个实例展示了如何进行UDP数据收发。客户端发送消息到服务器,服务器回应当前时间。
Windows Socket +UDP服务器客户端

     Winsock 是 Windows下套接字标准
        
         1.UDP socket编程

         UDP(用户数据报协议)是一个无连接,不可靠的数据传输,其特点是简单,快捷。相比与TCP,UDP不需要建立连接(不需connect、accept函数),数据发送接收之后,不需要终止连接。基于UDP的程序,避免了TCP运行的开销,在效率与速度上具有更好的表现。
         UDP是无连接的,可能会有数据的丢失,延迟,这些需要应用程序自己处理。
        
         2.UDP基本函数
         
创建socket
         SOCKET  socket (int af, int type, int protocol);
         第一个参数af:  表示族地址,网络编程一般使用AF_INET宏。
         第二个参数type:  表示连接类型,TCP可选面向连接SOCK_STREAM,UDP数据报SOCK_DGRAM。
         第三个参数protocol:  表示协议,在使用AF_INET族地址UDP连接,设为IPPROTO_UDP。
绑定socket:
         int  bind(SOCKET s, const struct sockaddr *saddr,int namelen);
         第一个参数:  需要绑定的socket。
         第二个参数:  对应AF_INET,使用struct sockaddr_in包含协议,IP,端口等信息。
         第三个参数:  对应AF_INET,使用struct sockaddr_in结构大小。
         该函数将socket与协议,IP地址,Port端口号绑定起来,相对于给socket“命名”唯一的标识,这样其他的进程就可以通过这个标识找到这个socket。
发送数据
         int  sendto(SOCKET s, const char  *buf,  int len,
                              int flags, const struct sockaddr  *to, int tolen);
         第一个参数:  socket为对方的socket。
         第二个参数:  发送数据的缓冲区。
         第三个参数:  数据缓冲区大小。
         第四个参数:  紧急状态,一般这为0。
         第五个参数:  可选,对应AF_INET,对方IP,端口等socket地址标识sockaddr_in。
         第六个参数:  可选,对应AF_INET,使用sockaddr_in结构大小。
         该函数用于UDP发送数据。
接收数据
         int  recvfrom(SOCKET s, char *buf, int len,
                                  int flags, struct sockaddr *from, int *fromlen );         
         第一个参数:  socket为对方的socket。
         第二个参数:  接收数据的缓冲区。
         第三个参数:  数据缓冲区大小。
         第四个参数:  紧急状态,一般这为0。
         第五个参数:  可选,对应AF_INET,返回对方IP,端口等socket地址标识sockaddr_in。
         第六个参数:  可选,对应AF_INET,使用sockaddr_in结构大小。
         该函数用于UDP接收数据。
绑定socket
         int  bind(SOCKET s, const struct sockaddr *saddr,int namelen);
         第一个参数:  需要绑定的socket。
         第二个参数:  对应AF_INET,使用struct sockaddr_in包含协议,IP,端口等信息。
         第三个参数:  对应AF_INET,使用struct sockaddr_in结构大小。
         该函数将socket与协议,IP,端口号绑定起来,相对于给socket“命名”唯一的标识,这样其他的进程就可以通过这个标识找到这个socket。
关闭套接字
          int  closesocket(SOCKET s);
          参数为socket。
          该函数用于关闭套接字。
         
          3.牛刀小试
          先在VC6.0运行服务器程序,再打开一个VC6.0运行客户端程序:
          UDPsever服务器等待来自客户端的信息,收到信息后打印出来,然后向客户端发送现在的时间。
          UDPclient客户端向服务器发送一个“Hello,server!”信息,然后接收来自服务器的时间信息并打印,重复三次。

运行效果:

UDP客户端程序:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
             
#include<stdio.h>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib")
int main ()
{
WSADATA wsa ;
SOCKET serversoc ;
SOCKADDR_IN serveraddr ;
SOCKADDR_IN peeraddr ;
int peer_len = sizeof ( peeraddr );
char Recv_buf [ 64 ];
//char *Server_IP="127.0.0.1";
char * Send_data = "Hello,server!" ;
int Send_len = strlen ( Send_data );
int time_out = 2000 ; //接收超时
int result ;
WSAStartup ( WINSOCK_VERSION , & wsa ); //初始化WS2_32.DLL
//命名协议,IP,端口
serveraddr . sin_family = AF_INET ;
serveraddr . sin_port = htons ( 13 );
serveraddr . sin_addr . s_addr = inet_addr ( "127.0.0.1" );
if ( serveraddr . sin_addr . s_addr == INADDR_NONE )
{
printf ( "不可用地址! \n " );
return - 1 ;
}
//创建套接字
serversoc = socket ( AF_INET , SOCK_DGRAM , 0 );
result = setsockopt ( serversoc , SOL_SOCKET , SO_RCVTIMEO ,( char * ) & time_out , sizeof ( time_out ));
for ( int i = 0 ; i < 3 ; i ++ )
{
//发送数据
result = sendto ( serversoc , Send_data , Send_len , 0 ,( SOCKADDR * ) & serveraddr , sizeof ( serveraddr ));
//接收数据
result = recvfrom ( serversoc , Recv_buf , 64 , 0 ,( SOCKADDR * ) & peeraddr , & peer_len );
if ( result >= 0 )
{
Recv_buf [ result ] = 0 ;
printf ( "接收数据为: %s \n " , Recv_buf );
}
}
closesocket ( serversoc );
WSACleanup ();
return 0 ;
}
来自CODE的代码片
UDPclient.c
UDP服务器程序:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
              
#include<stdio.h>
#include<winsock2.h>
#include<time.h>
#pragma comment(lib,"ws2_32.lib")
int main ()
{
WSADATA wsa ;
WSAStartup ( WINSOCK_VERSION , & wsa ); //初始化WS2_32.DLL
SOCKET serversoc ;
SOCKET clientsoc ;
SOCKADDR_IN serveraddr ;
SOCKADDR_IN clientaddr ;
int client_len = sizeof ( clientaddr );
int server_len = sizeof ( serveraddr );
char * Send_data ;
int Send_len ;
char Recv_buf [ 64 ];
int result ;
time_t nowtime ;
//命名协议,IP,端口
serveraddr . sin_family = AF_INET ;
serveraddr . sin_port = htons ( 13 );
serveraddr . sin_addr . s_addr = INADDR_ANY ;
//创建socket
serversoc = socket ( AF_INET , SOCK_DGRAM , 0 );
//绑定socket
result = bind ( serversoc , ( SOCKADDR * ) & serveraddr , server_len );
if ( result == SOCKET_ERROR )
{
printf ( "套接字绑定失败! \n " );
closesocket ( serversoc );
return - 1 ;
}
printf ( "Server is running..... \n " );
clientsoc = socket ( AF_INET , SOCK_DGRAM , 0 );
while ( 1 )
{
//接收数据
result = recvfrom ( serversoc , Recv_buf , 64 , 0 ,( SOCKADDR * ) & clientaddr , & client_len );
if ( result >= 0 )
{
Recv_buf [ result ] = 0 ;
printf ( "接收数据为: %s \n " , Recv_buf );
//发送数据
nowtime = time ( 0 );
Send_data = ctime ( & nowtime );
Send_len = strlen ( Send_data );
result = sendto ( clientsoc , Send_data , Send_len , 0 ,( SOCKADDR * ) & clientaddr , sizeof ( clientaddr ));
printf ( "Server is running..... \n " );
}
}
closesocket ( serversoc );
WSACleanup ();
return 0 ;
}
来自CODE的代码片
UDPserver.c


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值