基于TCPIP协议的SocketJAVA编程.docx
《基于TCPIP协议的SocketJAVA编程.docx》由会员分享,可在线阅读,更多相关《基于TCPIP协议的SocketJAVA编程.docx(22页珍藏版)》请在冰豆网上搜索。
基于TCPIP协议的SocketJAVA编程
基于TCP/IP协议的Socket JAVA编程
基于TCP/IP协议的Socket编程
1TCP/IP协议
2套接字(Socket)
2.1Client/Server模式
2.2套接字(Socket)概念
3Socket类和ServerSocket类
3.1Socket类
3.2ServerSocket类
4Socket编程应用举例
4.1Socket编程的基本步骤
4.2单客户/服务器Socket编程应用举例
4.3多客户/服务器Socket编程应用举例本章小结
1TCP/IP协议
TCP/IP协议(传输控制协议/网际协议)是一种网络通信协议,是一种面向连接的可靠的传输协议。
它规范了网络上的所有通信设备,尤其是一个主机与另一个主机之间的数据传输格式以及传送方式。
TCP/IP是Internet的基础协议。
TCP/IP协议的基本传输单位是数据包(datagram)。
TCP协议负责把数据分成若干个datagram,并给每个datagram加上包头;IP在每个包头上再加上接收端主机地址,以确定数据传输的目的地。
如果传输过程中出现数据丢失或数据失真等异常情况,TCP协议会自动要求数据重发,并重新分包。
TCP保证数据传输的质量,IP协议保证数据的传输。
TCP/IP协议数据的传输是基于TCP/IP模型的4层结构:
应用层、传输层、网络层和网络接口层。
在TCP/IP协议组中两种主要协议
1、传输层协议
有两个主要的传输层协议:
传输控制协议(TCP)和用户数据报协议(UDP)。
(1)传输控制协议(TCP)TCP传输数据建立在面向连接的基础上,实现了一种“虚电路”的概念。
双方通信之前,先建立连接,然后双方即可在其上发送数据流,发送完毕后再关闭连接。
这种数据交换方式的优点是效率高,缺点是建立连接和关闭连接需要额外的开销。
(1)TCP协议主要提供下列服务:
1.可靠的数据传输
2.面向连接的虚电路
3.缓冲的传输
4.重新排序
5.多路复用技术
6.高效的、全双工传输
7.流量控制
TCP协议提供的是一种可靠的数据流服务。
得到的是一个顺序的无差错的数据流。
(2)用户数据报协议(UDP)。
UDP是比TCP简单得多的协议,是对IP协议组的扩充。
由于大多数网络应用程序都在同一台机器上运行,计算机上必须能够确保目的地址机器上的软件程序能从源地址机器处获得数据包,以及源计算机能收到正确的回复。
这是通过使用UDP的“端口号”完成的。
源端口号标识了请求域名服务的本地计算机的应用程序,同时需要将所有由目的主机生成的响应包都指定到源主机的这个端口上。
(3)UDP与TCP比较
与TCP不同,UDP提供的是面向无连接、“不可靠”的数据报服务。
它不提供对IP协议的可靠机制、流控制以及错误恢复功能等。
由于UDP比较简单,比TCP负载消耗少。
主要用于不需要TCP排序和流量控制能力而是自己完成这些功能的应用程序。
2、应用层协议
在应用层中定义了许多高层协议:
(1)TELNET(远程终端访问)。
TELNET连接是一个TCP连接。
允许一台计算机上的用户登录到远程计算机上并进行交互。
支持终端到终端的连接及进程到进程分布式计算的通信。
(2)FTP(文件传输协议)FTP使得主机间可以共享文件。
FTP使用TCP生成一个虚拟连接用于控制信息,然后再生成一个单独的TCP连接用于数据传输。
FTP主要提供文件共享、支持间接使用远程计算机、使用户不因各类主机文件存储器系统的差异而受影响、可靠且有效的传输数据等功能。
(3)SMTP(简单邮件传输协议)SMTP支持在因特网上传递电子邮件,用于可靠且有效的数据传输。
它保证把各种类型的电子邮件通过这一协议从一台邮件服务器发送到另一台邮件服务器上。
(4)DNS(域名服务)DNS提供域名到IP地址的转换,允许对域名资源进行分散管理。
(5)HTTP(超文本传输协议)是Web浏览器和Web服务器之间通信的标准协议。
它指明客户端如何与服务器建立连接,客户端如何从服务器请求数据,服务器如何响应请求,最后连接如何关闭等。
HTTP连接是一个TCP连接。
TCP/IP模型中还有其他一些协议,如地址解析协议(ARP)、因特网控制消息协议(ICMP)等。
2套接字(Socket)
套接字允许程序员把网络连接当成一个流(Stream),并向这个流读写字节。
Socket对程序员掩盖了网络的低层细节,如纠错、包大小、包重传、网络地址等。
本节将介绍Client/Server模式、套接字(Socket)概念。
2.1Client/Server模式
计算机网络最重要的3个功能是数据通信、资源共享和分布处理。
为了满足这些功能需求,计算机网络产生了两种重要的应用模式:
客户端/服务器(Client/Server,C/S)模式和浏览器/服务器(Brower/Server,B/S)模式。
采用何种应用模式在编程实现时非常重要。
下面将主要介绍C/S模式。
在C/S模式下,客户向服务器发出服务请求,服务器接收到请求后,提供相应的服务。
其工作方式可通过现实生活中一个例子来说明。
在一个酒店中,顾客向服务员点菜,服务员把点菜单通知厨师,厨师按点菜单做好菜后让服务员端给顾客,这就是一种C/S工作方式。
如果把酒店看作一个系统,服务员就是客户端,厨师就是服务器,这种系统分工和协同工作的方式就是C/S的工作模式。
由此可见,工作在C/S模式下的系统被分成两大部分:
(1)客户端部分:
为每个用户所专有的,负责执行前台功能。
(2)服务器部分:
由多个用户共享的信息与功能,招待后台服务。
C/S模式建立的基础C/S模式的建立基于以下两点:
一是建立网络的起因是网络中软硬件资源、运算能力和信息不均等,需要共享,从而造就拥有众多资源的主机提供服务,资源较少的客户请求服务这一非对等作用。
二是网间进程通信完全是异步的,相互通信的进程既不存在父子关系,又不共享内存缓冲区,因此需要一种机制为希望通信的进程建立联系,为二者的数据交换提供同步,这就是基于C/S的TCP/IP。
图1基于C/S模式系统结构
C/S模式在操作过程中采取“请求/响应”的工作模式。
当用户需要访问服务器资源时由客户端发出请求,服务器接收到请求后做出响应,然后执行相应的服务,把执行结果返回到客户端,再由客户端作一定处理后返回给用户。
执行过程如下:
(1)服务器侦听相应端口的请求;
(2)客户端发出一个请求;
(3)服务器接收到此请求;
(4)服务器处理这个请求,并把处理结果返回给客户端。
从上面所描述的过程可知:
客户与服务器进程的作用是非对称的,因此编码不同。
服务进程一般是先于客户请求而启动的。
只要系统运行,该服务进程一直存在,直到正常或强迫终止。
2.2套接字(Socket)概念
数据在Internet中是以有限大小的分组的形式传输的。
一个分组是一个数据报,包括首部和负载。
首部包含目的的地址和端口、源地址和端口以及用于保证可靠传输的各种其他管理信息。
负载包含数据本身。
但由于分组长度有限,通常必须将数据分解为多个分组,在目的地再重新组合。
在传输过程中,有可能发生一个或多个分组丢失或被破坏的情况,此时就需要重传分组。
或者分组乱序到达,则需要重新排序。
这些工作将是非常繁重的。
幸运的是,套接字(Socket)的出现使我们不必关心这些事情,我们只需要把网络看成一个流,就象对文件操作一样对这个流进行操作就行了。
套接字(Socket)是网络协议传输层提供的接口。
Socket是两个程序之间进行双向数据传输的网络通讯端点,有一个地址和一个端口号来标识。
每个服务程序在提供服务时都要在一个端口进行,而想使用该服务的客户机也必须连接该端口。
图2基于Socket的点对点通信
目前共有两种套接字
1.流套接字提供一个面向连接的、可靠的数据传输服务,保证数据无差错、无重复、按顺序发送。
具有流量控制功能。
数据被看作字节流,无长度限制。
TCP即是一种基于流套接字的通信协议。
2.数据报套接字提供一个面向无连接的数据传输服务,不保证数据传输是可靠的、有序的、无重复的。
UDP即是一种基于数据报套接字的通信协议。
本章主要介绍基于TCP/IP协议的C/S模式下的Socket编程。
图3基于TCP/IP的Socket通信模式
在该种模式下,Socket可以看成是在两个程序进行通信连接中的一个端点,一个程序将一段信息写入Socket中,该Socket将这段信息发送到另外一个Socket中,使这段信息能传送到其他程序。
每一个基于TCP/IP的程序都赋予了一个端口号(0~65535),通过不同的端口号,区别服务器上运行的每一个应用程序和所提供的服务。
值得注意的是,习惯上将低于1024的端口号保留给系统服务使用。
在两个网络应用程序发送和接收信息时都需建立一个可靠的连接,流套接字依靠TCP来保证信息正确到达目的地。
实际上,IP分组有可能在网络中丢失或者在传送过程中发生错误。
当任何一种情况发生时,作为接收方的TCP将请求发送方TCP重发这个IP分组。
因此,两个流套接字之间建立的连接是可靠的连接。
Socket可进行的基本操作
(1)连接远程主机
(2)发送数据
(3)接收数据
(4)关闭连接
(5)绑定端口
(6)侦听入站数据
(7)在所绑定端口上接收远程主要的连接
利用Socket编程的一般步骤:
(1)分别为服务器和客户端创建Socket对象,建立Socket连接。
(2)打开连接到Socket的输入输出流。
Socket对象包含两个流:
一个是输入流,表示流入的数据流,其作用是接收数据;一个是输出流,表示流出的数据流,其作用是向外发送数据,其流操作与I/O流相同。
(3)按照一定的协议对Socket进行读/写操作,在本章里是基于TCP/IP协议;
(4)读/写操作结束后,关闭Socket连接。
3Socket类和ServerSocket类
在Java语言中,服务器端Socket使用ServerSocket类,客户端Socket使用Socket类,由此来区别服务器端和客户端。
3.1Socket类
.Socket类是Java用来实现客户端TCP操作的基础类,在Java编程中一切与TCP有关的操作包括连接的建立、传输、连接关闭及Socket选项的设置都由Socket类负责,这个类本身使用直接代码通过主机操作系统的本地TCP栈进行通信。
Socket类的输入输出都是通过流来实现的。
Socket类常用方法如下:
1.Socket类的构造函数
(1)publicSocket(Stringhost,intport)throwsUnknownHostException,IOException功能:
在客户端以指定的服务器host和端口号port创建一个Socket对象,并向服务器发出连接请求。
参数:
host:
服务器主机名。
port:
端口号。
若域名服务器无法解析该服务器名或域名服务器没有运行,此时host无法可知,则抛出UnknownHostException异常;若生成Socket时发生I/O错误则抛出IOException异常。
(2)publicSocket(InetAddressaddress,intport)throwsIOException功能:
在客户端以指定的服务器地址address和端口号port创建一个Socket对象,并向服务器发出连接请求。
参数:
address:
服务器IP地址。
port:
端口号。
若生成Socket时发生I/O错误则抛出IOException异常。
(3)publicSocket(Stringhost,intport,booleanstream)throwsIOException功能:
在客户端以指定的服务器host和端口号port创建Socket对象,并向服务器发出连接请求。
如果stream值为true,则创建流Socket对象,否则创建数据报Socket对象。
参数:
host:
服务器名。
port:
端口号。
stream:
创建流Socket对象或创建数据报Socket对象的标志。
若生成Socket时发生I/O错误则抛出IOException异常。
(4)publicSocket(InetAddressaddress,intport,booleanstream)throwsIOException功能:
在客户端以指定的服务器IP地址address和端口号port创建Socket对象,并向服务器发出连接请求。
如果stream值为true,则创建流Socket对象,否则创建数据报Socket对象。
参数:
address:
服务器IP地址。
port:
端口号。
stream:
创建流Socket对象或创建数据报Socket对象的标志。
若生成Socket时发生I/O错误则抛出IOException异常。
(5)publicSocket(InetAddressaddress,intport,InetAddresslocalAddr,intlocalPort)throwsIOException功能:
生成一个Socket并且连接到由address指定的服务器的端口port上。
该Socket将捆绑到由localAddr指定的本地主机的localPort端口上。
参数:
address:
服务器IP地址。
port:
端口号。
localAddr:
本地主机的IP地址。
localPort:
本地主机上的端口号。
若生成Socket时发生I/O错误则抛出IOException异常。
(6)publicSocket(Stringhost,intport,InetAddresslocalAddr,intlocalPort)throwsIOException功能:
生成一个Socket并且连接到由host指定的服务器的端口port上。
该Socket将捆绑到由localAddr指定的本地主机的localPort端口上。
参数:
host:
服务器名。
port:
端口号。
localAddr:
本地主机的IP地址。
localPort:
本地主机上的端口号。
若生成Socket时发生I/O错误则抛出IOException异常。
(7)protectedSocket(SocketImplimpl)throwsSocketException功能:
根据用户指定的SocketImpl生成一个无连接的socket。
参数:
impl:
子类希望用在Socket上的SocketImpl实例。
建立无连接失败时抛出SocketException异常。
客户端流Socket的创建可通过使用Socket类的构造函数完成。
构造函数不仅可以创建Socket对象,并且会尝试连接服务器端的Socket。
可通过这个方法测试某个端口的连接是否允许。
2.与Socket数据读写有关的常用方法
(1)publicInetAddressgetInetAddress()
功能:
获取创建socket连接时指定服务器的IP地址。
(2)publicInetAddressgetLocalAddress()
功能:
获取创建socket连接时客户端主机的IP地址。
(3)publicintgetPort()
功能:
获取创建Socket连接时指定的服务器的端口号。
(4)publicintgetLocalPort()
功能:
获取创建Socket连接时客户端的端口号。
(5)publicInputStreamgetInputStream()throwsIOException
功能:
为当前的socket对象创建输入流。
(6)publicOutputStreamgetOutputStream()throwsIOException
功能:
为当前的socket对象创建输出流。
(7)publicStringtoString()
功能:
转换该Socket成一个String.字符串表示。
3.关闭Socket连接的方法
publicsynchronizedvoidclose()throwsIOException
功能:
关闭建立的Socket连接。
当通信结束时,应调用该方法关闭Socket连接。
若在关闭Socket连接时发生I/O错误则抛出IOException异常。
【例1】
//创建socket连接后获取socket连接的相关信息
import.*;
importjava.io.*;
publicclassSocketInfo{
publicstaticvoidmain(Stringargs[]){
try{
Socketsktobj=newSocket("",8080);
System.out.println("1:
connectto"+sktobj.getInetAddress()+"onport"+sktobj.getPort());
System.out.println("2:
fromport"+sktobj.getLocalPort()+"of"+sktobj.getLocalAddress());
}
catch(UnknownHostExceptione){System.out.println(e);}
catch(IOExceptione){System.out.println(e);}
}
}
运行结果:
图4
【例2】
//客户端向服务器发送一个字符串,服务器接收并返回
import.*;
importjava.io.*;
publicclassSocketAppClient{
publicstaticvoidmain(Stringargs[]){
intport=134;
try{
Socketsc=newSocket("127.0.0.1",port);//创建本地socket连接
OutputStreamout=sc.getOutputStream();
DataOutputStreamdout=newDataOutputStream(out);
//获取输出流,并创建相应的数据输出流
dout.writeUTF("Tom"); //将tom写入输出流
InputStreamin=sc.getInputStream();
DataInputStreamdin=newDataInputStream(in);
//获取输入流,并创建相应的数据输入流
Stringstr=din.readUTF();
System.out.println(str);
in.close();
out.close();
sc.close();
}
catch(UnknownHostExceptione){System.out.println(e);}
catch(IOExceptione){System.out.println(e);}
}
}
运行结果:
单方通信,缺服务器
图5
3.2ServerSocket类
ServerSocket类用在服务器端,侦听和响应客户端的连接请求,并接收客户端发送的数据。
ServerSocket类的主要任务是在服务器端耐心地等候客户端的连接请求,一旦客户端应用程序申请建立一个Socket连接,ServerSocket类就会通过accept()方法返回一个对应的服务器端Socket对象,以便进行直接通信。
从两台计算机连接成功时起,服务器端与客户端就得到了一个真正的“Socket-Socket”连接。
1.ServerSocket类构造函数
(1)publicServerSocket(intport)throwsIOException
功能:
创建一个指定端口号的服务器端的socket。
请求连接队列的最大队列长度为50,若连接请求到达时队列已满,则拒绝连接。
端口号为0指在任何空闲端口上创建socket。
参数:
port:
端口号。
若无法创建Socket并绑定于所请求的端口号则抛出IOException异常。
(2)publicServerSocket(intport,intbacklog)throwsIOException
功能:
创建一个指定端口号的服务器端的socket。
请求连接队列的最大队列长度设置为backlog,若连接请求到达时队列已满,则拒绝连接。
端口号为0指在任何空闲端口上创建socket。
参数:
port:
端口号。
backlog:
请求连接队列的最大长度。
若无法创建Socket并绑定于所请求的端口号则抛出IOException异常。
(3)publicServerSocket(intport,intbacklog,InetAddressbindAddr)throwsIOException
功能:
创建一个指定端口号的服务器端的socket。
请求连接队列的最大队列长度设置为backlog,若连接请求到达时队列已满,则拒绝连接。
端口号为0指在任何空闲端口上创建socket。
与其它构造函数不同的是,该构造函数要指定要绑定到的本地IP地址。
主要用于在多IP地址系统上运行的服务器。
此时,它允许先把所侦听的地址,服务器Socket只在指定的地址侦听入站连接,不会侦听通过主机其他地址进入的连接。
其他构造函数默认绑定本地主机的所有IP地址。
当bindAddr为null时,缺省地接受对任何所有本地IP地址的连接。
参数:
port:
端口号。
backlog:
请求连接队列的最大长度。
bindAddr:
将捆绑到的本地IP地址.
若无法创建Socket并绑定于所请求的端口号则抛出IOException异常。
【例3】
//采用ServerSocket类查询端口号为130~140的端口号中哪个端口可创建连接。
import.*;
importjava.io.*;
publicclassPortScan2{
publicstaticvoidmain(Stringargs[]){
Stringhost="localhost";
for(inti=130;i<140;i++)
try{ServerSocketa=newServerSocket(i);
//在端口号i创建连接
System.out.println("thereisas