第14章 网络编程.ppt_第1页
第14章 网络编程.ppt_第2页
第14章 网络编程.ppt_第3页
第14章 网络编程.ppt_第4页
第14章 网络编程.ppt_第5页
已阅读5页,还剩46页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、网络编程,IP地址与端口,TCP/IP协议层次结构,信息与封装,TCP,IP,C/S服务模式,Winsock编程接口,Berkeley Socket,WinSock1.1,WinSock2.0,Winsock支持面向连接的通信和无连接通信两种方式。 面向连接的编程模式 无连接的编程模式,使用socket编程需要在头部加载Winsock2.h 并在link选项中的Object/library中添加Ws2_32.lib.,基于TCP的基本通信过程,服务器端: 1.加载套接字库 2.创建套接字(socket) 3.将套接字绑定到一个IP地址和端口(bind) 4.将套接字设置为监听模式(listen

2、) 5.等待客户请求,当请求到来后,返回一个新的套接字用于此连接(accept) 6.用返回的套接字与客户通信 返回等待另一请求,客户端: 1.加载套接字库 2.创建套接字(socket) 3.向服务器端发出请求(connect) 4.和服务器端进行通信 5.发送/接收消息(send/recv) 6.关闭套接字,基于UDP的基本通信过程,服务器(接收)端: 1.加载套接字库 2.创建套接字(socket) 3.将套接字绑定到一个IP地址和端口(bind) 4. 等待接收数据(recvfrom) 5.关闭套接字,客户(发送)端: 1.加载套接字库 2.创建套接字(socket) 3.向服务器端发

3、送数据(sendTo) 4.关闭套接字,加载Socket动态库 WS2_32.DLL ,并协商可用Socket版本 (1).int WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData ) 该函数成功时,返回0,否则为错误代码,1、加载Socket,其中:nVersionRequested参数用于指定要加载的Winsock库版本,高位字节指定次版本,低位字节指定主版本。可以使用MAKEWORD(x,y)宏设置(x是高位字节,y是低位字节)。,LpWSAdata是指向WSADATA结构的指针。该结构的定义如下: typedef stru

4、ct WSAData WORD wVersion; /获准使用的版本 WORD wHighVersion; /该库可以支持的最高版本 char szDescriptionWSADESCRIPTION_LEN+1; /无用 char szSystemStatusWSASYS_STATUS_LEN+1; /无用 char szSystemStatusWSASYS_STATUS_LEN+1;/无用 unsigned short iMaxSockets; /假定的可同时打开的套接字数 unsigned short iMaxUdpDg; /假定的可接受的数据报的长度 char FAR * lpVendo

5、rInfo; /无用 WSADATA, FAR * LPWSADATA; LOBYTE(wVresion)=主版本号 HIBYTE(wVresion)=次版本号,加载Socket,加载Socket,例如: WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, ,2、创建socket,创建套接字 SOCKET socket ( int af, int type, int protocol ) 该函数调用

6、成功返回一个SOCKET结构,否则返回INVALID_SOCKET ,错误信息可通过 WSAGetLastError();获得 其中: Af参数指定一个地址族,同时也指定了准备使用那种协议,对于TCP/IP只能是AF_INET Type参数指定套接字的类型,一些协议只能使用某些套接字。 Protocol参数指定使用那一种具体协议。为0时自动根据前面信息选择协议,创建socket,常用的组合: 协议 地址族(af) 套接字类型(type) 协议(Protocol) IP AF_INET TCP SOCK_STREAM IPPROTO_IP UDP SOCK_DGRAM IPPROTO_UDP 例

7、如,要创建基于TCP/IP协议的套接字,则有, SOCKET s = socket(AF_INET, SOCK_STREAM,IPPROTO_IP),3、绑定地址,一台主机可以拥有多个IP地址,绑定地址的目的是通知主机,本程序在哪个IP哪个端口上监听 int bind ( SOCKET s,/刚创建的套接字 struct sockaddr FAR* name,/地址 int namelen )/地址长度,绑定地址,其中: S参数是一个套接字,表示该套接字将在name参数指定的地址名字上执行操作。 name 参数是一个指向struct sockaddr结构的指针。该参数随使用的协议不同而不同。在

8、TCP/IP中常用sockaddr_in 代替: struct sockaddr_in short sin_family; /AF_INET u_short sin_port; /端口号 struct in_addr sin_addr; char sin_zero8; /填充字段 ;,绑定地址- in_addr,ip地址为四个字节,为提供地址方法的灵活性,因此定义了联合体,可以用4个字节或两个短整数或一个长整数方式给出地址 typedef struct in_addr union struct u_char s_b1,s_b2,s_b3,s_b4 S_un_b; /4BYTE struct u

9、_short s_w1,s_w2 S_un_w; /2SHORT u_long S_addr; /1LONG S_un; in_addr; 示例: struct sockaddr_in tcpaddr; tcpaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);,绑定地址,例如, SOCKET s; int port=5150;/指定端口号要大于1024,避开常用端口 s = socket(); struct sockaddr_in tcpaddr; tcpaddr.sin_family = AF_INET; tcpaddr.sin_port = hto

10、ns(port); tcpaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); bind(s,(SOCKADDR*) 注:只有一台机器拥有多个网卡(IP)时,才需要指定在哪个IP监听,否则一般取值INADDR_ANY 此时可能需要下面两个函数 inet_addr()/点分十进制字符串 to long inet_ntoa()/long to 点分十进制字符串,网络字节和主机字节的转换 将主机字节转换为网络字节: u_short htons ( u_short hostshort ) u_long htonl ( u_long hostlong ) 将网络字

11、节转换为主机字节: u_short ntohs ( u_short netshort ) u_long ntohl ( u_long netlong ),网络字节和主机字节的转换,等待连接,int listen( SOCKET s, int backlog ); /等待队列最大长度,通常设为SOMAXCONN ,由系统决定一个合理长度,接受请求,SOCKET accept( SOCKET s, struct sockaddr* addr,/发送方的IP int* addrlen ); /需要给定初始值,然后得到确定值 例如: sockaddr_in client_addr; int len=s

12、izeof(sockaddr); while(1) SOCKET SessionSock= accept( s, (sockaddr* ) ,接收消息,int recv( SOCKET s, char* buf, int len, int flags ); /通常设为0,int send( SOCKET s, const char* buf, int len, int flags );,关闭与卸载,当Socket不再使用时: int closesocket( SOCKET s ); 程序退出前,卸载Winsock库 int WSACleanup(),客户端的过程,1、加载Socket DLL

13、2、创建Socket 3、请求连接 int connect( SOCKET s, const struct sockaddr* name, /服务器IP int namelen ); 4、断开连接 5、卸载Winsock,单线程TCP通信程序示例与分析,实例:TcpDemo 分析: 由于单线程的原因,服务器端同时只能为一个用户服务,必须等一个用户释放连接后才能接受下一个用户的请求 由于不是Windows中的消息驱动机制,收发次序由程序决定,没有收到信息时,不能发送,就相当于“一个人聊天时只能应答,不能主动发言”,基于UDP的通信-接收端,1、加载套接字库 2、创建套接字 SOCKET sock

14、Srv=socket(AF_INET,SOCK_DGRAM,0); 3、绑定监听地址 4、等待接收recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*),基于UDP的通信-发送端,1、加载套接字库 2、创建套接字 SOCKET sockClient=socket(AF_INET,SOCK_DGRAM,0); 3、发送数据 sendto(sockClient,Hello,strlen(Hello)+1,0, (SOCKADDR*),UDP完成一次发送过程示例,示例:UdpDemo 分析:此例只能完成一次单向的信息传送,如果要做到对话,必须双方都建立发送SOCKET和

15、接收SOCKET 只能使用IP地址,而不能使用主机名,名字解析,各协议族都有自己地址解析机制。 IP网络的地址解析函数: gethostbyaddr 该函数根据IP地址得到主机名。 HOSTENT FAR * gethostbyaddr ( const char FAR * addr, /指向要查找的IP地址 int len, /addr的长度 int type /类型,为 AF_INET );,名字解析,gethostbyname 该函数根据主机名得到IP地址。 struct hostent FAR * gethostbyname ( const char FAR * name /指向要查找

16、的主机名 ) 该函数返回struct hostent结构。,struct hostent,struct hostent char FAR *h_name; /是正式的主机名 char FAR * FAR * h_aliases; /是由主机备用名组成的数组 short h_addrtype; /表示返回的地址族 short h_length; / h_addr_list参数的长度 char FAR * FAR * h_addr_list; /是用由主机IP地址组成的列表,是网络字节 ;,名字解析,gethostname 得到本地主机名 int gethostname ( char FAR *

17、name, int namelen ) inet_addr将IP地址的点分格式转换为正确的IN_ADDR结构。 unsigned long inet_addr ( const char FAR * cp ) inet_ntoa 将Internet IP地址转换为点分格式 char FAR * inet_ntoa ( struct in_addr in ),名字解析示例,WSADATA lpd; char HostName101,*p; struct in_addr in; HOSTENT *h; unsigned long *pp; WSAStartup(MAKEWORD(2,2),阻塞模式与

18、非阻塞模式,Windows套接字在两种模式下执行I/O操作:阻塞模式与非阻塞模式,在阻塞模式下,等待接受不能继续执行,一般采用多线程方式编程,以解决进程的等待问题。,阻塞模式下多线程解决方案,启动: listen(ListenSock,5); AfxBeginThread( . ,非阻塞模式:,通过控制套接字函数 int ioctlsocket ( SOCKET s, long cmd, /控制标志,FIONBIO:清楚阻塞标记 u_long FAR* argp )/ 0:cmd Disable 1: cmd Enable 将一个套接字设置为非锁定模式。,非阻塞模式:,例如, unsigned

19、 int ul=1;/ul非0值非阻塞模式 s = socket(AF_INET,SOCK_STREAM,0); ioctlsocket(s, FIONBIO , (unsigned long *) 在Winsock中共有5种套接字I/O模型:选择模型、异步选择模型、事件选择模型、重叠模型和完成端口模型。,选择模型(Select),中心是利用select()函数,通过该函数可以判断套接字上是否存在可读的数据,或能否向一个套接字写入数据。该函数的目的是防止应用程序在套接字处于锁定模式时,在一次I/O调用中,进入锁定状态。,select函数的格式如下:,int select ( int nfds,

20、 /被忽略 fd_set FAR * readfds,/检查可读性,是否有可读的数据 fd_set FAR * writefds,/检查可写性,是否有可写的数 fd_set FAR * exceptfds,/检查是否有带外数据 const struct timeval FAR * timeout /struct timeval的指针,确定该函数执行的等待时间,当为NULL时,无限期等待,直到有一个满足的条件返回),select函数参数说明,fd_set是一个集合,常用的操作宏: FD_CLR(s,*set): 从set中删除s FD_ISSET(s,*set): 检查s是否是set的一个元素。

21、 FD_SET(s,*set): 将s加入set FD_ZERO(*set): 将set初始化为空集合 struct timeval long tv_sec; /以秒为单位指定时间 long tv_usec; /以毫秒为单位指定时间 ;,select举例,SOCKET s; fd_set fds; int ret; while(1) FD_ZERO( If(ret=SOCKET_ERROR) /Error else if(FD_ISSET(s, HWND hWnd; s=socket(); WSAAsyncSelect(s,hWnd,WM_SOCKET, FD_ACCEPT|FD_CLOSE)

22、; ,WSAAsyncSelect举例,BOOL CALLBACK WndProc(HWND hWnd, UINT uMsg,WPARAM wParam,LPARAM lParam) SOCKET Accept; Switch(uMsg) case WM_SOCKET:/自定义的消息 if(WSAGETSELECTERROR(lParam) closesocket(wParam); break; switch(WSAGETSELECTEVENT(lParam) case FD_ACCEPT: case FD_CLOSE: ,WSAAsyncSelect完整示例,ChatRome,MFC中的Winsock,主要有CAsyncSocket和CSocket类。 CasyncSocket类封装了Winsock API,和Winsock编程的方法几乎一样。CS

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论