| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1739 人关注过本帖, 1 人收藏
标题:[转载]WINSOCKAPI的例子
只看楼主 加入收藏
学习VB才2天
Rank: 5Rank: 5
等 级:贵宾
威 望:16
帖 子:1653
专家分:0
注 册:2006-5-4
收藏(1)
 问题点数:0 回复次数:4 
[转载]WINSOCKAPI的例子

WinSockAPI的使用..

1.WSAStartup 函数

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

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

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

初始化1.1版本

lngRetVal = WSAStartup(&H101, udtWinsockData)

初始化2.2版本

lngRetVal = WSAStartup(&H202, udtWinsockData)

第二个参数是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

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

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

3.建立Socket函数

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

函数有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)
s=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)

4.关闭Socket函数

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

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

5.连接函数

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

6.套接字绑定函数

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

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()函数转换。

7.套接字监听函数

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

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

8.接受连接请求

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仍可以接受其他可户端的连接请求。

9.接收信息

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包头的一个特定标志来决定。

10.发送信息
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
参数参看接收信息
四,服务器与客户机交互
目前最常用的方法是:服务程序在一个众所周知的地址(其中包括端口信息)监听对服务的请求,也就是说,服务进程一直处于休眠状态,直到一个客户对这个服务的地址提出了连接请求。这个时刻,服务程序被唤醒并对客户的请求作出适当的反应。注意,服务器与客户机之间的交互可以是面向连接的(基于流套接字),也可以是无连接的(基于数据报套接字)。
服务器
socket()
|
bind()
|
listen() 客户机
|
| socket()
| 建立连接 |
accept() <------------------------- connect()
| 请求数据 |
recv() <----------------------------- send()
| |
处理服务请求 |
| 应答数据 |
send() ------------------------------> recv()
| |
close() close()





下面是WINSOCKAPI的例子..

yTtXtbWS.rar (93.2 KB) [转载]WINSOCKAPI的例子


[此贴子已经被作者于2006-8-15 8:45:41编辑过]



06S63VEP.rar (93.2 KB) [转载]WINSOCKAPI的例子

搜索更多相关主题的帖子: WINSOCKAPI 例子 
2006-08-15 08:43
leon2
Rank: 3Rank: 3
等 级:新手上路
威 望:7
帖 子:731
专家分:0
注 册:2005-3-18
收藏
得分:0 
沙发...
好东西当然要收藏!
有一个问题,我想在 Winsock 缓冲区有数据时才接收,应该在哪里调用 recv 函数呢?
看来只能用 Timer 定时接收了。

[此贴子已经被作者于2006-8-15 12:09:10编辑过]

2006-08-15 12:01
redice
Rank: 3Rank: 3
等 级:新手上路
威 望:6
帖 子:902
专家分:0
注 册:2006-12-11
收藏
得分:0 
非常好,谢谢

鲲鹏数据 - 专业Web数据采集服务提供者
http://www.
2007-01-26 19:04
oilight
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2012-1-17
收藏
得分:0 
收下了。谢谢。
2012-01-17 14:27
boy8199
Rank: 1
等 级:新手上路
帖 子:4
专家分:4
注 册:2007-11-15
收藏
得分:0 
收藏 回去看看,好老的帖子啊
2014-08-26 17:50
快速回复:[转载]WINSOCKAPI的例子
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.012980 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved