网络编程基础.pdf
3 Sept.2008 Neusoft Confidential网络编程基础网络编程基础一一.TCP/IP概述概述应用层物理层数据链路层网络层传输层会话层表示层OSI参考模型应用层网络层传输层网络接口层TCP/IP参考模型1.1 分层模型分层模型应用层应用层(Application Layer)在应用层用户调用程序通过TCP/IP互联网来访问可行的服务。传输层传输层(Transport Layer)传输层负责提供应用程序之间的通信服务。这种通信又称为端到端通信。传输层管理信息的流动,提供可靠的传输服务,以确保数据到达无差错、无乱序。为了达到这个目的,传输层协议要进行协商,让接收方回送确认信息及让发送方重发丢失的分组。传输层协议软件把要传输的数据流划分为分组,把每个分组连同目的地址交给网络层去发送。网络层网络层(Internet Layer)网络层负责选择主机之间通信用数据报的传输路径,即路由。网络接口层网络接口层(Network Interface Layer)网络接口层是TCP/IP协议软件的最底层,负责将二进制流转换为数据帧,并进行发送和接收。应用层网络层传输层网络接口层TCP/IP参考模型1.2 消息消息封装封装1.3 TCP/IP协议族协议族1.4 TCP/IP核心协议核心协议TCP(Transmission Control Protocol)传输控制协议,基于连接的服务UDP(User Datagram Protocol)用户数据报协议,无连接的服务IP(Internet Protocol)Internet协议,信息传递机制1.4.1 TCP协议协议TCPTCP向应用层提供可靠的面向对象的数据流传输服务,TCP数据传输实现了从一个应用程序到另一个应用程序的数据传递。它能提供高可靠性通信(即数据无误、数据无丢失、数据无失序、数据无重复到达的通信),应用程序通过向TCP层提交数据接发送/收端的地址和端口号而实现应用层的数据通信三次握手TCP是面向连接的,所谓面向连接,就是当计算机双方通信时必需先建立连接,然后进行数据通信,最后拆除连接三个过程。TCP在建立连接时又分三步走:第一步:主机A向主机B发送一个包含同步标志的TCP报文。第二步:主机B在收到客户端的SYN报文后,将返回一个SYN+ACK的报文,表示主机B的请求被接受。第三步:主机A也返回一个确认报文ACK给服务器端,同样TCP序列号被加一,到此一个TCP连接完成。1.4.1 TCP协议协议 SYN J SYN K,ACK J+1 ACK K+1 三次握手三次握手UDPUDP即用户数据报协议,是一种面向无连接的不可靠传输协议,不需要通过3次握手来建立一个连接,同时,一个UDP应用可同时作为应用的客户或服务器方。由于UDP协议并不需要建立一个明确的连接,因此建立UDP应用要比建立TCP应用简单得多。UDP比TCP协议更为高效,也能更好地解决实时性的问题,如今,包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都使用UDP协议。1.4.2 UDP协议协议二二.Socket编程编程独立于具体协议的网络编程接口独立于具体协议的网络编程接口在在TCP/IP模型中,主要位于传输层和应用层之间模型中,主要位于传输层和应用层之间应用层程序应用层程序IP数据链路层与物理层数据链路层与物理层TCPUDP流套接字接口流套接字接口数据报套接字接口数据报套接字接口原始套接字接口原始套接字接口2.1 什么是什么是Socket套接字是一个通信终结点,它是套接字是一个通信终结点,它是Socket应用程序用来在网应用程序用来在网络上发送或接收数据包的对象络上发送或接收数据包的对象套接字具有类型,与正在运行的进程相关联,并且可以有套接字具有类型,与正在运行的进程相关联,并且可以有名称名称套接字一般只用同一种高层协议进行通信。也就是说,不套接字一般只用同一种高层协议进行通信。也就是说,不可能通信的一端用可能通信的一端用TCP,而另一端用,而另一端用UDP2.2 什么是套接字什么是套接字应用程序应用程序A套接字套接字A应用程序应用程序B套接字套接字B套接字通信模型套接字通信模型在在Linux中套接字中套接字(socket),是一种特殊的,是一种特殊的I/O接口,它接口,它也是一种文件描述符。是一种常用的进程之间通信机制,通也是一种文件描述符。是一种常用的进程之间通信机制,通过它不仅能实现本地机器上的进程之间的通信,而且通过网过它不仅能实现本地机器上的进程之间的通信,而且通过网络能够在不同机器上的进程之间进行通信。络能够在不同机器上的进程之间进行通信。每一个每一个socket用一个相关描述用一个相关描述协议、本地地址、本地端协议、本地地址、本地端口、远程地址、远程端口口、远程地址、远程端口来表示。来表示。socket也有一个类似于打也有一个类似于打开文件的函数调用,该函数返回一个整型的开文件的函数调用,该函数返回一个整型的socket描述符,描述符,随后的连接建立、数据传输等操作都是通过随后的连接建立、数据传输等操作都是通过socket来实现的。来实现的。2.2 什么是套接字什么是套接字2.3 Scoket类型类型 流式套接字(流式套接字(SOCK_STREAM)流式套接字使用流式套接字使用TCP协议,提供面向连接的通信流;协议,提供面向连接的通信流;数据报套接字(数据报套接字(SOCK_DGRAM)数据报套接字使用数据报套接字使用UDP协议,提供面向无连接的服务;协议,提供面向无连接的服务;原始套接字(原始套接字(SOCK_RAW)原始套接字允许对底层协议如原始套接字允许对底层协议如IP或或ICMP进行直接访问;进行直接访问;2.4 地址与端口地址与端口在网络上,一个在网络上,一个Socket的标识主要借助于地址和端口来描述的标识主要借助于地址和端口来描述地址指该套接字所在计算机的网络地址,可以为域名或地址指该套接字所在计算机的网络地址,可以为域名或IP地地址的形式址的形式同一机器上可以运行多个网络应用程序,每个应用程序都有同一机器上可以运行多个网络应用程序,每个应用程序都有自己的套接字用以进行网络通信,此时如果只有地址标识套接自己的套接字用以进行网络通信,此时如果只有地址标识套接字,则当一个通信包到达机器时,将无法确定究竟是哪个应用字,则当一个通信包到达机器时,将无法确定究竟是哪个应用程序的套接字需要接收此信息。由此增加了端口的概念,以协程序的套接字需要接收此信息。由此增加了端口的概念,以协助区分同一机器上不同应用程序的套接字助区分同一机器上不同应用程序的套接字端口用于标识进程,同一机器上不同的网络应用程序各有不端口用于标识进程,同一机器上不同的网络应用程序各有不同的端口,这样,通过“网络地址同的端口,这样,通过“网络地址+端口号”的标识方法,便端口号”的标识方法,便唯一标识了机器上的应用程序了唯一标识了机器上的应用程序了某些端口是专门为公共服务保留的(某些端口是专门为公共服务保留的(Ftp:21,http:80),除),除非程序是要提供这些服务,否则应尽量避免使用这些端口。非程序是要提供这些服务,否则应尽量避免使用这些端口。端口端口1024以前的端口号都是系统保留的或是作为公共服务的,以前的端口号都是系统保留的或是作为公共服务的,应尽量选择大于应尽量选择大于1024的端口号,以避免冲突的端口号,以避免冲突2.4 地址与端口地址与端口2.5 Client/server通信模型通信模型在客户在客户/服务器模式中我们将请求服务的一方称为服务器模式中我们将请求服务的一方称为客户(客户(client),将提供某种服务的一方称为服务),将提供某种服务的一方称为服务器(器(server)一个服务程序通常在一个众所周知的地址一个服务程序通常在一个众所周知的地址监听监听对对服务的请求,也就是说服务进程一直处于休眠状服务的请求,也就是说服务进程一直处于休眠状态,直到一个客户对这个服务的地址提出了连接态,直到一个客户对这个服务的地址提出了连接请求。在这个时刻,服务程序被“惊醒”并且为请求。在这个时刻,服务程序被“惊醒”并且为客户提供服务客户提供服务对客户的请求作出适当的对客户的请求作出适当的反应反应2.6 常用函数常用函数socket创建套接字创建套接字bind绑定本机端口绑定本机端口connect建立连接建立连接listen监听端口监听端口accept接受连接接受连接recv,recvfrom数据接收数据接收send,sendto数据发送数据发送close,shutdown关闭套接字关闭套接字2.6.1 IP地址转换函数地址转换函数inet_addr()点分十进制数表示的点分十进制数表示的IP地址转换为地址转换为网络字节序的网络字节序的IP地址地址inet_ntoa()网络字节序的网络字节序的IP地址转换为点分十地址转换为点分十进制数表示的进制数表示的IP地址地址2.6.2 socket()函数语法函数语法2.6.3 bind()函数语法函数语法2.6.4 listen()函数语法函数语法2.6.5 accept()函数语法函数语法2.6.6 connect()函数语法函数语法2.6.7 send()函数语法函数语法2.6.8 recv()函数语法函数语法2.6.9 sendto()函数语法函数语法2.6.10 recvfrom()函数语法函数语法2.6.11 网络信息检索函数网络信息检索函数gethostname获得主机名获得主机名getpeername获得与套接口相连的远程协议地址获得与套接口相连的远程协议地址getsockname获得套接口本地协议地址获得套接口本地协议地址gethostbyname根据主机名取得主机信息根据主机名取得主机信息gethostbyaddr根据主机地址取得主机信息根据主机地址取得主机信息getprotobyname根据协议名取得主机协议信息根据协议名取得主机协议信息getprotobynumber根据协议号取得主机协议信息根据协议号取得主机协议信息getservbyname根据服务名取得相关服务信息根据服务名取得相关服务信息getservbyport根据端口号取得相关服务信息根据端口号取得相关服务信息getsockopt/setsockopt获取获取/设置一个套接口选项设置一个套接口选项ioctlsocket设置套接口的工作方式设置套接口的工作方式2.7 流式套接字编程流式套接字编程创建并初始化套接字创建并初始化套接字监听来自客户机的请求监听来自客户机的请求接受连接请求接受连接请求接收数据接收数据发送数据发送数据关闭连接关闭连接创建并初始化套接字创建并初始化套接字请求建立连接请求建立连接发送数据发送数据接收数据接收数据关闭连接关闭连接服务器客户机服务器客户机流式套接字(有连接通信)编程2.7 流式套接字编程流式套接字编程 socket 服务器端 close send/sendto recv/recvfrom accept listen bind socket close recv/recvfrom send/sendto connect客户端bind2.8 数据报套接字编程数据报套接字编程创建并初始化套接字创建并初始化套接字监听来自客户机的请求监听来自客户机的请求进行处理进行处理发送结果给客户端发送结果给客户端关闭连接关闭连接创建并初始化套接字创建并初始化套接字向服务器发出请求向服务器发出请求接收结果接收结果关闭连接关闭连接服务器客户机数据报套接字(无连接通信服务器客户机数据报套接字(无连接通信)编程编程2.8 数据报套接字编程数据报套接字编程socket closesendrecvacceptlistensocket closerecvsendconnectrecvfromsendtosendtorecvfrom三三.基于基于TCP的的socket编程步骤编程步骤服务器端:1.创建套接字:socket()#include#includeint socket(int domain,int type,int protocol)2.绑定套接字到一个IP地址和一个端口上:bind()#include#includeint bind(int sockfd,struct sockaddr*myaddr,int addrlen)3.将套接字设置为监听模式,以等待连接请求:listen()#includeint listen(int sockfd,int backlog)服务器端:4.请求到来后接受连接请求,并返回一个与此次连接对应的套接字:accept()#includeint accept(int sockfd,struct sockaddr*addr,int*addrlen)此时新建连接,并创建新的Socket套接字,此时addr为客户端的addr信息。5.用返回的套接字和客户端进行通信:recv()和send()int recv(int fd,char*buf,int len,unsigned int flags)int write(int fd,char*buf,int len,unsigned int flags)6.关闭当前的连接,进入等待状态,继续等待客户端的连接:close()#includeint close(int sockfd);7.关闭服务器端的套接字描述符:close()#includeint close(int sockfd);客户端:1.创建客户端套接字:socket()#include#includeint socket(int domain,int type,int protocol)2.向服务器发出连接请求:connect()#include#includeint connect(int sockfd,struct sockaddr*servaddr,int addrlen)其中参数servaddr指定远程服务器的套接字地址,包括服务器的IP地址和端口号3.和服务器端进行网络通信:recv()和send()int recv(int fd,char*buf,int len,unsigned int flags)int send(int fd,char*buf,int len,unsigned int flags)客户端:4、关闭套接字:close()#includeint close(int sockfd);