WinSocket 编程 (基于UDP)_妙不可言      不相信一见钟情,却相信日久生...

来源:百度文库 编辑:神马文学网 时间:2024/03/29 19:42:32
查看文章   WinSocket 编程 (基于UDP)2009-04-29 09:32 对于在一个无连接套接字上接收数据的进程来说,步骤并不复杂。先用WSAStartup来加载Winscock DLL相应版本,然后用socket或WSASocket建立套接字。再把这个套接字和准备接收数据的接口绑定在一起。这是通过b i n d函数来完成的。和面向连接会话不同的是,我们不必调用l i s t e n和a c c e p t。 1、Winsock的初始化       每个Wi n s o c k应用都必须加载Winsock DLL的相应版本。如果调用Wi n s o c k之前,没有加载Wi n s o c k库,这个函数就会返回一个S O C K E T _ E R R O R,错误信息是W S A N O T I N I T I A L I S E D。加载Wi n s o c k库是通过调用W S A S t a r t u p函数实现的。这个函数的定义如下:       int WSAStartup(
                                     WORD
wVersionRequested,
                                       LPWSADATA lpWSAData
                                    );       wVersionRequested                 [in] Highest version of Windows Sockets support that the caller can use. The high-order byte specifies the minor version (revision) number; the low-order byte specifies the major version number.        lpWSAData                [out] Pointer to the WSADATA data structure that is to receive details of the Windows Sockets implementation.         The WSAStartup function returns zero if successful. Otherwise, it returns one of the error codes listed in the following. An application cannot call WSAGetLastError to determine the error code as is normally done in Windows Sockets if WSAStartup fails. The Ws2_32.dll will not have been loaded in the case of a failure so the client data area where the last error information is stored could not be established. Error code Meaning WSASYSNOTREADY Indicates that the underlying network subsystem is not ready for network communication. WSAVERNOTSUPPORTED The version of Windows Sockets support requested is not provided by this particular Windows Sockets implementation. WSAEINPROGRESS A blocking Windows Sockets 1.1 operation is in progress. WSAEPROCLIM Limit on the number of tasks supported by the Windows Sockets implementation has been reached. WSAEFAULT The lpWSAData is not a valid pointer. 注释:         The WSAStartup function must be the first Windows Sockets function called by an application or DLL. It allows an application or DLL to specify the version of Windows Sockets required and retrieve details of the specific Windows Sockets implementation. The application or DLL can only issue further Windows Sockets functions after successfully calling WSAStartup. (在使用Windows Sockets 之前必须调用WSAStartup 加载Winsocket库成功)   Once an application or DLL has made a successful WSAStartup call, it can proceed to make other Windows Sockets calls as needed. When it has finished using the services of the Ws2_32.dll, the application or DLL must call WSACleanup to allow the Ws2_32.dll to free any resources for the application.(在使用完Ws2_32.dll需要调用WSACleanup ) int WSACleanup (void); 例子:   The following code fragment demonstrates how an application that supports only version 2.2 of Windows Sockets makes a WSAStartup call:
WORD wVersionRequested;            WSADATA wsaData;            int err;            wVersionRequested = MAKEWORD( 2, 2 );            /*wVersionRequested参数用于指定准备加载的Winsock库的版本。高位字节指定所需要的
Winsock库的副版本,而低位字节则是主版本。然后,可用宏MAKEWORD( X , Y )(其中,x是
高位字节, y是低位字节)方便地获得wVersionRequested的正确值。*/ err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { /* Tell the user that we could not find a usable */ /* WinSock DLL. */ return; } /* Confirm that the WinSock DLL supports 2.2.*/ /* Note that if the DLL supports versions greater */ /* than 2.2 in addition to 2.2, it will still return */ /* 2.2 in wVersion since that is the version we */ /* requested. */ if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) { /* Tell the user that we could not find a usable */ /* WinSock DLL. */ WSACleanup( ); return; } /* The WinSock DLL is acceptable. Proceed. */
 
2、创建套接字
            
SOCKET socket(                    int af,                           int type,                         int protocol                     );
af
[in] Address family specification. 对于TCP/IP只能是AF_INET
type
[in] Type specification for the new socket. The following are the only two type specifications supported for Windows Sockets 1.1: TypeExplanation SOCK_STREAM Provides sequenced, reliable, two-way, connection-based byte streams with an OOB data transmission mechanism. Uses TCP for the Internet address family. SOCK_DGRAM Supports datagrams, which are connectionless, unreliable buffers of a fixed (typically small) maximum length. Uses UDP for the Internet address family.
In Windows Sockets 2, many new socket types will be introduced
and no longer need to be specified, since an application can
dynamically discover the attributes of each available transport
protocol through the WSAEnumProtocols function. Socket type
definitions appear in Winsock2.h, which will be periodically
updated as new socket types, address families, and protocols are
protocol
[in] Protocol to be used with the socket that is specific to the
indicated address family. 指定为0,系统会根据地址格式和套接字类别,自动选择一个合适的协议。
例子:
SOCKET sockSrv=socket(AF_INET,SOCK_DGRAM,0);
 
3、把这个套接字和准备接收数据的地址和
接口绑定在一起
int bind(                  SOCKET s,                                            const struct sockaddr FAR *name,                     int namelen                                         );
s
[in] Descriptor identifying an unbound socket. (需要邦定的套接字)
name
[in] Address to assign to the socket from the SOCKADDR structure. (指向SOCKADDR结构的指针)
namelen
[in] Length of the value in the name parameter. (地址结构的长度)
            
struct sockaddr {                      u_short    sa_family;                      char       sa_data[14];                     };
 
            
struct sockaddr_in{            short sin_family;            unsigned short sin_port;            IN_ADDR sin_addr;            char sin_zero[8];
                  };
sin_family
Address family; must be AF_INET.
sin_port
Internet Protocol (IP) port.
sin_addr
IP address in network byte order.
   typedef struct in_addr {    union {     struct{     unsigned char s_b1,     s_b2,    s_b3,     s_b4;     } S_un_b;     struct {     unsigned short s_w1,     s_w2;    } S_un_w;    unsigned long S_addr;     } S_un;    } IN_ADDR;
sin_zero
Padding to make structure the same size as SOCKADDR.
例子:
sockaddr_in addrSrv;
addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000);
bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
 
 
4、发送数据
int sendto(            SOCKET s,                                               const char FAR *buf,                                   int len,                                                int flags,                                              const struct sockaddr FAR *to,                         int tolen                                              );
s
[in] Descriptor identifying a (possibly connected) socket.
buf
[in] Buffer containing the data to be transmitted.
len
[in] Length of the data in buf.
flags
[in] Indicator specifying the way in which the call is made.
to
[in] Optional pointer to the address of the target socket.
tolen
[in] Size of the address in to.
例子:
sendto(sockClient,"Hello",strlen("Hello")+1,0,
         (SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
 
 
5、接收数据
            
int recvfrom(                    SOCKET s,                                       char FAR* buf,                                  int len,                                        int flags,                                      struct sockaddr FAR *from,                      int FAR *fromlen                               );
s
[in] Descriptor identifying a bound socket.
buf
[out] Buffer for the incoming data.
len
[in] Length of buf.
flags
[in] Indicator specifying the way in which the call is made.
from
[out] Optional pointer to a buffer that will hold the source address upon return.
fromlen
[in, out] Optional pointer to the size of the from buffer.
例子: SOCKADDR_IN addrClient; int len=sizeof(SOCKADDR); char recvBuf[100]; recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&len); 代码: #include 工程—〉设置—〉连接—〉对象/库模块 加入Ws2_32.lib 接收端: WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 1, 1 );

err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
   return;
}


if ( LOBYTE( wsaData.wVersion ) != 1 ||
        HIBYTE( wsaData.wVersion ) != 1 ) {
   WSACleanup( );
   return;
}

SOCKET sockSrv=socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000);

bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

SOCKADDR_IN addrClient;
int len=sizeof(SOCKADDR);
char recvBuf[100];
int a;
   a=recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&len);
   if(SOCKET_ERROR==a)
    break;
   printf("%s\n",recvBuf);

closesocket(sockSrv);
WSACleanup(); 发送端: WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 1, 1 );

err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
   return;
} if ( LOBYTE( wsaData.wVersion ) != 1 ||
        HIBYTE( wsaData.wVersion ) != 1 ) {
   WSACleanup( );
   return;
} SOCKET sockClient=socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000);

sendto(sockClient,"Hello",strlen("Hello")+1,0,
   (SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
closesocket(sockClient);
WSACleanup();