注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

风雨夜归人

专业收集资料,个人爱好!

 
 
 

日志

 
 

WinSockAPI在易语言中的应用  

2009-05-20 00:13:02|  分类: 易语言 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
WinSockAPI的使用

1.WSAStartup 函数

    为了在你的应用程序当中调用任何一个Winsock API 函数,首先第一件事情你就是必须通过WSAStartup函数完成对Winsock 服务的初始化,因此需要调用WSAStartup函数。

Declare Function WSAStartup Lib "ws2_32.dll" _
    (ByVal wVersionRequired As Long, lpWSAData As WSAData) As Long

--代码开始--易语言格式--只需要复制红色字符部分--
.版本 2

.DLL命令 WSAStartup, 整数型, "ws2_32.dll", "WSAStartup", 公开, 初始化winsock,成功返回0,失败返回错误代码。
    .参数 wVersionRequired, 整数型, , 指定了你想载入的Winsock版本,其高字节指定了次版本号,而低字节指定了主版本号。
    .参数 lpWSAData, WSAData, 传址, 指向WSAData结构的指针,WSAStartup会向该结构中填充其载入的Winsock动态链库的信息。

--代码结束--易语言格式--只需要复制红色字符部分--


    这个函数有两个参数: wVersionRequired 和 lpWSAData。wVersionRequired 参数定义Windows Sockets 提供能使用的最高版本,它的高位字节定义的是次版本号,低位字节定义的是主版本号。下面的2个Winsock版本在VB中使用的例子:

初始化1.1版本

lngRetVal = WSAStartup(&H101, udtWinsockData)

初始化2.2版本

lngRetVal = WSAStartup(&H202, udtWinsockData)

--代码开始--易语言格式--只需要复制红色字符部分--
.版本 2

.子程序 载入WinSock, 整数型, 公开, 成功返回0,失败返回错误号
.参数 版本, 整数型
.参数 WinSock信息, WSAData, 参考 可空

返回 (WSAStartup (版本, WinSock信息))

--代码结束--易语言格式--只需要复制红色字符部分--



第二个参数是WSADATA 的数据结构 ,它是接收Windows Sockets 执行时的数据。

Type WSAData
   wVersion       As Integer
   wHighVersion   As Integer
   szDescription  As String * WSADESCRIPTION_LEN
   szSystemStatus As String * WSASYS_STATUS_LEN
   iMaxSockets    As Integer
   iMaxUdpDg      As Integer
   lpVendorInfo   As Long
End Type

--代码开始--易语言格式--只需要复制红色字符部分--
.版本 2

.数据类型 WSAData, 公开
    .成员 wVersion, 整数型
    .成员 wHighVersion, 整数型
    .成员 szDescription, 字节型, , "256"
    .成员 szSystemStatus, 字节型, , "129"
    .成员 iMaxSockets, 整数型
    .成员 iMaxUdpDg, 整数型
    .成员 lpVendorInfo, 整数型
--代码结束--易语言格式--只需要复制红色字符部分--


数据成员的描述在下表中:

Field                       描述 
wVersion               Windows Sockets 版本信息。 
wHighVersion          通过加载库文件得到的最高的支持Winsock 的版本,
                      它通常和wVersion值相同。 
szDescription         Windows Sockets 执行时的详细描述 
szSystemStatus        包含了相关的状态和配置的信息 
iMaxSockets           表示同时打开的socket最大数,为0表示没有限制。 
iMaxUdpDg             表示同时打开的数据报最大数,为0表示没有限制。 
lpVendorInfo          厂商指定信息预留 

在Winsock的1.1和2.2版本中没有lpVendorInfo的返回值。因为winsock 2支持多个传输协议,所以iMaxSockets 和iMaxUdpDg只能在仅支持TCP/TP的winsock1.1中使用。为了在Winsock 2中获得这些值,你可以使用WSAEnumProtocols 函数。

如果成功或者返回一个错误代码,则函数返回 0。

错误代码                            含义 
WSASYSNOTREADY         指出网络没有为传输准备好。 
WSAVERNOTSUPPORTED     当前的WinSock实现不支持应用程序指定的Windows Sockets规范版本 
WSAEINPROGRESS         一个阻塞WinSock调用正在进行 
WSAEPROCLIM            请求的协议没有在系统中配置或没有支持它的实现存在。 
WSAEFAULT              lpWSAData 不是有效的指针


2.WSACleanup 函数

每次调用了WSAStartup函数,你都需要调用WSACleanup函数,通知系统来卸载库文件及清除已分配的资源,这个函数十分简单,没有任何参数:

Declare Function WSACleanup Lib "ws2_32.dll" () As Long

--代码开始--易语言格式--只需要复制红色字符部分--
.版本 2

.DLL命令 WSACleanup, 整数型, "ws2_32.dll", "WSACleanup", 公开
--代码结束--易语言格式--只需要复制红色字符部分--



3.建立Socket函数

Declare Function socket Lib "ws2_32.dll" (ByVal af As Long, _ 
                  ByVal s_type As Long, 
                  ByVal Protocol As Long) As Long

--代码开始--易语言格式--只需要复制红色字符部分--
.版本 2

.DLL命令 socket, 整数型, "ws2_32.dll", "socket", 公开
    .参数 af, 整数型
    .参数 s_type, 整数型
    .参数 Protocol, 整数型

--代码结束--易语言格式--只需要复制红色字符部分--



函数有3个参数定义建立何种socket,三个参数分别是:
Argument          Description                                           Enum Type 
af                     Address family specification.                     AddressFamily 
s_type              Type specification for the new socket.      SocketType 
Protocol            Protocol to be used with the socket         SocketProtocol
                       that is specific to the indicated address 
                       family.

AddressFamily:
    AF_UNSPEC = 0        '/* unspecified */
    AF_UNIX = 1          '/* local to host (pipes, portals) */
    AF_INET = 2          '/* internetwork: UDP, TCP, etc. */
    AF_IMPLINK = 3       '/* arpanet imp addresses */
    AF_PUP = 4           '/* pup protocols: e.g. BSP */
    AF_CHAOS = 5         '/* mit CHAOS protocols */
    AF_NS = 6            '/* XEROX NS protocols */
    AF_IPX = AF_NS       '/* IPX protocols: IPX, SPX, etc. */
    AF_ISO = 7           '/* ISO protocols */
    AF_OSI = AF_ISO      '/* OSI is ISO */
    AF_ECMA = 8          '/* european computer manufacturers */
    AF_DATAKIT = 9       '/* datakit protocols */
    AF_CCITT = 10        '/* CCITT protocols, X.25 etc */
    AF_SNA = 11          '/* IBM SNA */
    AF_DECnet = 12       '/* DECnet */
    AF_DLI = 13          '/* Direct data link interface */
    AF_LAT = 14          '/* LAT */
    AF_HYLINK = 15       '/* NSC Hyperchannel */
    AF_APPLETALK = 16    '/* AppleTalk */
    AF_NETBIOS = 17      '/* NetBios-style addresses */
    AF_VOICEVIEW = 18    '/* VoiceView */
    AF_FIREFOX = 19      '/* Protocols from Firefox */
    AF_UNKNOWN1 = 20     '/* Somebody is using this! */
    AF_BAN = 21          '/* Banyan */
    AF_ATM = 22          '/* Native ATM Services */
    AF_INET6 = 23        '/* Internetwork Version 6 */
    AF_CLUSTER = 24      '/* Microsoft Wolfpack */
    AF_12844 = 25        '/* IEEE 1284.4 WG AF */
    AF_MAX = 26

Socket types:
    SOCK_STREAM = 1      ' /* stream socket */
    SOCK_DGRAM = 2       ' /* datagram socket */
    SOCK_RAW = 3         ' /* raw-protocol interface */
    SOCK_RDM = 4         ' /* reliably-delivered message */
    SOCK_SEQPACKET = 5   ' /* sequenced packet stream */

Protocols:
    IPPROTO_IP = 0       '/* dummy for IP */
    IPPROTO_ICMP = 1     '/* control message protocol */
    IPPROTO_IGMP = 2     '/* internet group management protocol */
    IPPROTO_GGP = 3      '/* gateway^2 (deprecated) */
    IPPROTO_TCP = 6      '/* tcp */
    IPPROTO_PUP = 12     '/* pup */
    IPPROTO_UDP = 17     '/* user datagram protocol */
    IPPROTO_IDP = 22     '/* xns idp */
    IPPROTO_ND = 77      '/* UNOFFICIAL net disk proto */
    IPPROTO_RAW = 255    '/* raw IP packet */
    IPPROTO_MAX = 256


该函数可以建立使用特定协议的网络套接字

例如
对于UDP协议可以这样写:
s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)

对于TCP协议可以这样写:
s=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)

--代码开始--易语言格式--只需要复制红色字符部分--
.版本 2

.子程序 创建Socket, 逻辑型, 公开, 该函数如果调用成功就返回新创建的套接字的描述符
.参数 协议族, 整数型, , AF_系列常量。
.参数 套接字类型, 整数型, , SOCK_系列常量。
.参数 通信协议, 整数型, , IPPROTO_系列常量

Socket套接字 = socket (协议族, 套接字类型, 通信协议)
返回 (Socket套接字 ≠ 0)

--代码结束--易语言格式--只需要复制红色字符部分--



4.关闭Socket函数

Declare Function closesocket Lib "ws2_32.dll" (ByVal s As Long) As Long

--代码开始--易语言格式--只需要复制红色字符部分--
.版本 2

.DLL命令 closesocket, 整数型, "ws2_32.dll", "closesocket", 公开, 关闭Socket函数
    .参数 s, 整数型, , 建立socket时的Handle  socket套接字

--代码结束--易语言格式--只需要复制红色字符部分--


函数有一个参数为建立socket时的Handle


5.套接字帮定函数

Declare Function bind Lib "ws2_32.dll" (ByVal s As Long, _
                  ByRef name As sockaddr_in, _
                  ByRef namelen As Long) As Long

--代码开始--易语言格式--只需要复制红色字符部分--
.版本 2

.DLL命令 bind, 整数型, "ws2_32.dll", "bind", 公开, 绑定端口
    .参数 s, 整数型, , 建立socket时的Handle  socket套接字
    .参数 name, sockaddr_in
    .参数 namelen, 整数型

--代码结束--易语言格式--只需要复制红色字符部分--


s是使用Socket函数创建好的套接字,name指向描述通信对象的结构体的指针,namelen是该结构的长度。该结

构体中的分量包括:
IP地址:对应name.sin_addr.s_addr

端口号:对应name.sin_port
        端口号用于表示同一台计算机上不同的进程(即应用程序),其分配方法有两种:
        第一种分配方法是,进程让系统为套接字自动分配一端口号,这只要在调用bind前将端口号指定为0即可。由系统自动分配的端口号位于1024~5000之间,而1~1023之间的任一TCP或UDP端口都是保留的,系统不允许任一进程使用保留端口,除非其有效用户ID是零(即超级用户)。
        第二种分配方法是,进程为套接字指定一特定端口。这对于需要给套接字分配一众所周知的端口的服务器是很有用的。指定范围在1024~65536之间。

地址类型:对应name.sin_family,一般都赋成AF_INET,表示是internet地址(即IP 地址)。IP地址通常使用点分表示法表示,但它事实上一个32位的长整数,这两者之间可通过inet_addr()函数转换。


6.套接字监听函数

Declare Function listen Lib "ws2_32.dll" (ByVal s As Long, ByVal backlog As Long) As Long

listen函数用来设定Socket为监听状态,这种状态表明Socket准备被连接了。注意,此函数一般在服务程序上使用,其中s是使用Socket函数创建好的套接字,backlog参数用于设定等待连接的客户端数。



7.接受连接请求

Declare Function accept Lib "ws2_32.dll" (ByVal s As Long, ByRef addr As sockaddr_in, _
                                          ByRef addrlen As Long) As Long


服务端应用程序调用此函数来接受客户端Socket连接请求,accept()函数的返回值为一新的Socket,新Socket就可用来完成服务端和客户端之间的信息传递与接收,而原来Socket仍可以接受其他可户端的连接请求。


8.接收信息

Declare Function recv Lib "ws2_32.dll" (ByVal s As Long, _
                                        ByRef buf As Any, _
                                        ByVal buflen As Long, _
                                        ByVal flags As Long) As Long 


s    一个已连接的socket的识别符 
buf   接受到的数据的缓冲区 
len   缓冲区长度 
flags 指定从哪调用的标识 

第一个参数是socket的句柄-为socket函数返回值。那就是说:我们需要告诉recv函数,哪一个socket正访问函数。

第二个参数是:函数执行之后能装载一些数据的缓冲区。但它不是必须要有足够的长度接收Winsock缓冲区的所有数据,缓冲区的大小限制为8192 字节 (8 Kbytes)。因此如果Winsock缓冲区的数据的大小大于recv函数的缓冲区,你必需多次调用此函数,直到获取所有的数据。

如果应用程序定义缓冲区的长度,则recv函数必须知道缓冲区可以存放多少字节。第三个参数就是为了这个目的。

最后一个参数是可选的,今天我们不使用。该参数有两个选择标志: MSG_PEEK 和 MSG_OOB,用于改变函数的行为。

MSG_PEEK 从输入数据中取数。数据拷入缓冲区,但不从输入队列中移走。函数返回当前准备接收的字节数。  
MSG_OOB 处理OOB(Out-of-band带外)数据。在网络上有两种类型的数据包,正常包和带外包。带外包可以通过检验一个TCP/IP包头的一个特定标志来决定。


9.发送信息

Declare Function send Lib "ws2_32.dll" (ByVal s As Long, _
                                        ByRef buf As Any, _
                                        ByVal buflen As Long, _
                                        ByVal flags As Long) As Long 


参数参看接收信息



10.连接函数[客户端连接]

Declare Function connect Lib "ws2_32.dll" (ByVal s As Long, _
                                           ByRef name As sockaddr_in, _
                                           ByVal namelen As Long) As Long

参数 

s             连接的socket句柄。

name       建立连接的地址。

namelen    连接地址的长度。 

返回值

成功时返回0。否则返回SOCKET_ERROR以及一个对应的错误号 Err.LastDllError。

显然在调用这个函数时我们需要知道socket句柄,将连接的电脑的端口号和主机名称(或主机IP地址)。我们知道Winsock 控件的Connect方法依靠两个变量:RemoteHost 和RemotePort。此方法不需要socket句柄,因其已经被封装在COM对象中。你也许认为connect函数应该也接受相同的变量设置,然而,事实并非如此。connect函数的主机地址和端口号的传送是依靠 sockaddr_in 结构。

Public Type sockaddr_in
    sin_family       As Integer
    sin_port         As Integer
    sin_addr         As Long
    sin_zero(1 To 8) As Byte
End Type





服务器与客户机交互

目前最常用的方法是:服务程序在一个众所周知的地址(其中包括端口信息)监听对服务的请求,也就是说,服务进程一直处于休眠状态,直到一个客户对这个服务的地址提出了连接请求。这个时刻,服务程序被唤醒并对客户的请求作出适当的反应。注意,服务器与客户机之间的交互可以是面向连接的(基于流套接字),也可以是无连接的(基于数据报套接字)。


            服务器

           socket()
              |
            bind()
              |
           listen()                                       客户机
              |
              |                                        socket()
              |                     建立连接               |
           accept()   <-------------------------       connect()
              |                     请求数据               |
            recv()   <-----------------------------     send()
              |                                            |
         处理服务请求                                      |
              |                      应答数据              |
            send()    ------------------------------>   recv()
              |                                            |
           close()                                      close()


WinSockAPI
               优点:功能强大,支持多种协议,使用灵活,WinSockAPI调用的wsock32.dll(28K)或ws2_32.dll(69K)为Windows系统自带函数库不必担心缺少文件。
               缺点:使用复杂,编程量大,需要一定基础
               适合于要求较高的网络程序
  评论这张
 
阅读(2303)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017