WinSock网络编程Word格式文档下载.docx
《WinSock网络编程Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《WinSock网络编程Word格式文档下载.docx(39页珍藏版)》请在冰点文库上搜索。
①TCP(传输控制协议)
提供虚电路和面向连接的数据流传输服务。
实现无差错无重复的顺序数据传输。
陈家琪:
《计算机网络》WinSock网络编程第1页共23页
②UDP(用户数据报协议)
提供无连接的数据报传输服务。
数据通过相互独立的报文进行传输,是无序的,并且不保证可靠、无
差错。
3.WinSockDLL
WinSock与操作系统的关系
应用程序1
应用程序2
动态链接库
网络编程接口––如WinSockAPI
网络通信协议––如TCP/IP协议
操作系统––如Windows
物理通信介质
动态链接库:
1位6版:
WINSOCK.DLL3位2版:
WSOCK32.DLL
①DLL装载
WinSock服务由动态连接库WinSockDLL提供,
它完成WinSock的初始化任务,协商WinSock的版本支持,并分配
必要的资源。
在使用WinSockAPI之前,必须调用:
intWSAStartup(WORDv,(LPWSADATA)&
WD)
其中:
v–––指示应用程序对WinSock版本的要求,
低字节为主版本号,高字节为副版本号。
例:
v1.1v=Ox0101,v2.0v=Ox0002,
WD––返回WinSock的实现信息。
WD是一个WSADATA结构:
structWSADATA{
WORDwVersion;
WORDwHighVersion;
charszDescription[WSADESCRIPTION_LEN+1];
charszSystemStatus[WSASYSSTATUS_LEN+1];
unsignedshortiMaxSockets;
unsignedshortiMaxUdpDg;
charFAR*lpVendorInfo;
};
结构成员说明
wVersion:
DLL支持的WinSock规范的版本;
wHighVersion:
DLL可支持的WinSock规范的最高版本;
szDescription:
DLL的说明及厂商描述;
szSystemStatus:
DLL将相关的状态和配置信息;
iMaxSockets:
一个进程可以打开的最大套接口数目;
iMaxUdpDg:
应用程序发送或接收的最大UDP数据报的大小;
如果应用程序没有给出限制,iMaxUdpDg为0(隐
含为8192字节)。
最小值为512。
lpVendorInfo:
指向厂商规定数据结构的远指针。
调用成功,返回0。
②DLL卸载
当不需WinSockDLL的服务,释放DLL所使用的资源。
应用程序必须调用:
intWSACleanup()
对应于每一次WSAStartup()调用必须有一个WSACleanup()调用。
4.套接口Socket
Socket实际上是一个通信端口;
一个Socket是通讯的一端。
网络通信将通过各自的Socket相联系。
在应用开发中就像使用文件句柄一样,
应用程序向操作系统申请,
由操作系统分配本地唯一的Socket端口号。
然后,可以对Socket句柄进行读,写操作。
创建Socket:
SOCKETsocket(
intaf,//套接口所用地址族
inttype,//套接口类型
intprotocol//套接口所用协议
)
参数
说明
①af
AF_INET
TCP/IP地址
AF_UNIX
......
UNIX地址
②type
SOCK_STREAM
数据流套接口,对应TCP协议
SOCK_DGRAM
数据报套接口,对应UDP协议
③protocol
IPPROC_TCP
使用TCP/IP的TCP协议
IPPROC_UDP
使用TCP/IP的UDP协议
①和②基本确定了一种协议,若
调用者不想指定,设置为0。
返回值:
若无错误发生,socket()返回引用套接口的描述字(套接口号)。
否则的话,返回SOCKET_ERROR错误,即-1。
应用程序可通过WSAGetLastError()获取相应错误代码。
5.主机地址标识网络环境中的唯一通信端点标识。
包含:
协议、IP地址、端口。
(俗称三元组)
关于端口:
在TCP/IP中,TCP与UDP使用彼此独立的端口;
端口大小:
16bit(共216个)
端口分为:
①系统全局端口:
1~1023;
例,HTTP为TCP/80,FTP为TCP/21、UDP/69,SMTP为TCP/25
②系统自动分配端口:
1024~5000;
③自由端口:
5000~65535;
6.主机地址标识的数据结构
structsockaddr{
u_shortsa_family;
//协议族
charsa_data[14];
//主机地址标识(端口号、IP地址)
structsockaddr_in{
shortsin_family;
u_shortsin_port;
//16bit端口号,网络字节顺序
structin_addrsin_addr;
//32bit的IP地址,网络字节顺序
charsin_zero[8];
//未用
structin_addr{
u_longs_addr;
//32bit的IP地址,网络字节顺序
网络字节顺序:
16bit/32bit整数存放格式––高字节在前,低字节在后。
设置主机地址
//------------------------------------------------
voidSetSockAddr(structsockaddr_in*A,WORDPort,char*IP)
{
A->
sin_family
=
AF_INET;
//TCP/IP协议
sin_port
htons(Port);
//端口号。
sin_addr.s_addr
inet_addr(IP);
//IP地址。
}
函数
作用
htons()
把16bit的数字从主机字节顺序转换到网络字节顺序
inet_addr()
把一个IP地址格式"
A.B.C.D"
转换成32bit的网络字节顺序
注:
IntelCPU的主机字节顺序:
16bit/32bi整t
前,高字节在后。
数存放格式––低字节在
7.Socket号与主机地址捆绑
将IP地址和端口号与所创建的Socket号联系起来。
int
SOCKETs,//待捆绑Socket
structsockaddrfar*name,//赋予Socket的主机地址标识
intlen//name的长度
);
8.WinSock操作模式
①同步模式或阻塞模式(blockingmode)
采用DOS技术编程,某些WinSock函数(同步函数)直到完成操作后才
返回。
例,当执行数据接收函数revc()时,一直等待对方发送数据,直到接
收到数据后才返回。
②异步模式或非阻塞模式(non-blockingmode)
采用Windows技术编程,利用消息(事件驱动)的特点,使同步函数变
为异步函数(不产生阻塞)。
关键:
异步选择函数WSAAsyncSelect()的使用。
WSAAsyncSelect()可设置一个或多个网络事件消息,
如,已收到数据、数据发送完毕、客户机请求连接、服务器已完成连
接等网络事件。
当设置的网络事件发生时,Windows应用程序的窗口函数将收到一
个消息。
通过这个消息就可以进行相应的处理。
intWSAAsyncSelect(
SOCKETs,//需要事件驱动的套接口
HWNDhWnd,//接收消息的窗口句柄
unsignedintwMsg,//网络事件发生时的消息字
longlEvent//用于指明感兴趣的网络事件集合
lEvent参数由下表中列出的值组成:
值
意义
FD_READ
已接收到数据
FD_WRITE
数据发送完毕
FD_OOB
已接收到边带数据
FD_ACCEPT
客户机请求连接,用于服务器端
FD_CONNECT
服务器已完成连接,用于客户机端
FD_CLOSE
连接关闭(对方的套接口关闭)
WSAAsyncSelect(S,hW,WM_USER+1,FD_ACCEPT|FD_READ|FD_CLOSE);
程序结束时,应注销异步选择:
WSAAsyncSelect(S,hW,0,0);
9.无连接协议的同步模式编程无连接服务器一般都是面向事务处理的。
一个请求一个应答就完成了客户程序与服务程序之间的相互作用。
①工作过程:
服务器
客户机
S=socket(...)
bind(S,...)
recv(S,...)
阻塞,等待客户请求
处理服务请求
服务请求
sendto(S,...)
继续服务?
Y
N
closesocket(S)
服务应答
阻塞,等待服务数据
处理数据
继续?
Y
无连接套接口应用程序时序图
服务器首先启动,通过调用socket()建立一个套接口,然后bind()将该套接口和本地地址(IP地址和端口)联系在一起,服务器调用recv()等待接收数据。
客户机通过调用socket()建立一个套接口,然后bind()将该套接口和本地地址(IP地址和端口)联系在一起,客户机调用sendto()向服务器发送数据;
服务器的recv()接收到客户机的数据后,调用sendto()向客户机发送应答数据;
客户机的recv()便接收到了服务器的应答数据;
最后,待数据传送结束后,双方调用closesocket()关闭套接口。
②编程示例:
//UDP(TCP/IP)fortheconsoleapplication.
//
//VC6.0addWSOCK32.LIBinProject->
Settings...->
Link
#include"
stdafx.h"
#include<
winsock.h>
//byuser
stdlib.h>
WORDRPort=6666;
//远程端口RemotePort
charRIP[16]="
127.0.0.1"
;
//远程IP地址RemoteIPAddr
WORDLPort=7777;
//本地端口LocalPort
charLIP[16]="
//本地IP地址LocalIPAddr
SOCKETS;
//套接口SOCKET
structsockaddr_inrAddr;
//远程参数,remoteAddr
structsockaddr_inlAddr;
//本地参数,localAddr
WSADATAWD;
//WinSockDLL信息
intr;
//result;
//-----------------------------------------------
voidShowInfo(char*info)
{puts(info);
exit
(1);
}
sin_family=AF_INET;
//TCP/IP协议
sin_port=htons(Port);
//端口。
sin_addr.s_addr=inet_addr(IP);
//IP网址。
//------------------------------------------------voidmain()
WORDv;
//wVersionRequested;
//---------StartupWinSocket--------
v=0x0101;
//0x0101forv1.1,0x0002forv2.0r=WSAStartup(v,(LPWSADATA)&
WD);
if(r!
=0)ShowInfo("
Start_Error"
//---------CreateWinSocket--------S=socket(PF_INET,SOCK_DGRAM,0);
if(S==-1)ShowInfo("
Socket_Create_Error"
intl=sizeof(rAddr);
charMsg[80];
puts("
TypeexitthenQuitProgram!
"
SetSockAddr(lAddr,LPort,LIP);
r=bind(S,(structsockaddrfar*)&
lAddr,sizeof(lAddr));
if(r==-1)ShowInfo("
bind_Error"
SetSockAddr(&
rAddr,RPort,RIP);
do{
//---------SendMess--------puts("
Send:
gets(Msg);
if(!
strcmp(Msg,"
exit"
))break;
r=sendto(S,Msg,strlen(Msg),0,
(structsockaddrfar*)&
rAddr,l);
Send_Error"
//---------RecieveMess--------puts("
Sendok!
WaitingRecieve..."
r=recv(S,Msg,80,0);
//r=recvfrom(SD,Msg,80,0,(structsockaddrfar*)&
rAddr,&
l);
//发送套接口的主机地址信息存放在rAddr中
Recieve_Error"
Msg[r]=0;
puts(Msg);
Recieveok!
}while
(1);
closesocket(S);
WSACleanup();
return;
说明:
在VC中进行WinSockAPI编程开发,需要使用到下面三个文件:
①winsock.h
WinSockAPI的头文件
②wsock32.LIB
WinSockAPI的连接库,把它作为项目的非缺
的连接库包含到项目文件中去(Pr。
oject->
Settings...->
Link)
③wsock32.DLL
WinSockAPI的动态连接库,位于windows的系
统目录下(95/98:
system、NT:
system32)。
省
intsendto(//向一指定目的地发送数据
SOCKETs,//源套接口
char*buf,//待发送数据的缓冲区
intbuflen,//缓冲区中数据的长度
intflags,//调用方式标志位,一般取0
structsockaddrFAR*to,//指向目的套接口的主机地址
inttolen//目的套接口主机地址的长度
主要用于SOCK_DGRAM类型套接口向to参数指定端的套接口发送数据报。
对于
SOCK_STREAM类型套接口,to和tolen参数被忽略;
这种情况下sendto()等价于
send()。
intrecv(//从一个套接口接收数据
SOCKETs,//接收套接口
char*buf,//接收数据的缓冲区
intlen,//缓冲区中数据的长度
intflags//调用方式标志位,一般取0
intrecvfrom(//从一个套接口接收数据
structsockaddrFAR*from,//获取发送套接口的主机地址
intfromlen//发送套接口的主机地址的长度
10.无连接协议的异步模式编程
A.程序结构
WinMain(...)
WndProc(消息)
WM_CREATE
windows
消息处理
WSAStartup(...)
设置本地lAddr
bind(S,...,lAddr)
WSAAsyncSelect(S,...,USER+1,FD_READ)
设置服务器rAddr
USER+1
recvfrom(S,...,&
rAddr)
服务数据
sendto(S,...,rAddr)
处理服务数据
发送消息事件
WM_DESTROY
WSAAsyncSelect(S,...,0,0)closesocket(S)
WSACleanup()
return
UDP-WinSock-Windows应用程序结构图
服务器端口:
通过bind(),设置确定的服务器端口号;
服务器IP地址:
使用本地的主机IP地址;
客户机端口:
由操作系统自动分配;
可以不使用bind()。
客户机IP地址:
服务器收到客户机的服务请求时,revcfrom(S,...,&
rAddr)可获得客户机的主机地址信息rAddr,然后,发送sendto(S,...,rAddr)。
B.编程示例
①服务器程序
//服务器端口:
6666;
//服务器IP地址:
使用本机的主机IP地址;
//UDPSer01(TCP/IP)forthewindowsapplication.
/*VC6.0File->
New->
Projects->
选<
Win32Application>
项
(输入Projectname:
ServerW01->
按OK按钮)->
->
选<
asampleWin32Application>
项->
按Finish按钮->
按OK按钮->
...
//VC
//------------------------------------------------charTitle[]="
UDPSer01"
//窗口标题
HI