Java网络编程复习要点及实验_第1页
Java网络编程复习要点及实验_第2页
Java网络编程复习要点及实验_第3页
Java网络编程复习要点及实验_第4页
Java网络编程复习要点及实验_第5页
已阅读5页,还剩11页未读 继续免费阅读

付费下载

下载本文档

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

文档简介

1.对非可序列化对象调用序列化和反序列化方法会抛出IOExceptiontransient变量不会被序列化Static变量不会被初始化Externalizable接口中声明了两个方法:publicvoidwriteExternal(ObjectOutputout)throwsIOExceptionpublicvoidreadExternal(ObjectInputin)throwsIOException,ClassNotFoundExceptionwriteExternal()方法负责序列化操作readExternal()方法负责反序列化操作区别于默认反序列化方式:在对实现了Externalizable接口的类的对象进行反序列化时,会先调用类的默认(不带参数的)构造方法。由此可见,如果类实现了Externalizable接口,那么它必须具有public类型的不带参数的构造方法,否则这个类无法反序列化。2.判断两个Class实例是否相等可以使用==if(e.getClass()==Employee.class){…}获得Class对象表示类的完整类名getName()Java反射机制主要提供了以下功能:在运行时判断任意一个对象所属的类。在运行时构造任意一个类的对象。在运行时判断任意一个类所具有的成员变量和方法。在运行时调用任意一个对象的方法。生成动态代理。Java中的Object类是所有Java类的公共父类,是所有类继承的根,其内定义了应该在所有Java类中被改写的几个方法:hashCode()equals()clone()toString()getClass()在JDK中,主要由java.lang.reflect包中的类来实现Java反射机制:Class类:代表一个类型Field类:代表类的成员变量(成员变量也称为类的属性)Method类:代表类的方法Constructor类:代表类的构造方法Modifier类:Java中的各种修饰符Array类:提供了动态创建数组,以及访问数组的元素的静态方法远程调用:创建一个Call类作为传输类,其中封装了要调用的方法名称,参数类型、参数值以及方法执行的结果创建一个接口,作为通信双方事先约定的可以调用的方法在服务器端提供一个通信接口的实现类创建服务器程序创建客户端程序Call对象表示客户端发起的一个远程调用,它包括方法调用的类名或接口名、方法名、方法参数类型、方法参数值和方法执行结果。publicclassCallimplementsSerializable{privateStringclassName;//表示类名或接口名privateStringmethodName;//表示方法名privateClass[]paramTypes;//表示方法参数类型privateObject[]params;//表示方法参数值privateObjectresult;}TCP三次握手/四次挥手详解(转)2009-11-2611:23TCP(TransmissionControlProtocol)传输控制协议TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接:位码即tcp标志位,有6种标示:SYN(synchronous建立联机)ACK(acknowledgement确认)PSH(push传送)FIN(finish结束)RST(reset重置)URG(urgent紧急)Sequencenumber(顺序号码)Acknowledgenumber(确认号码)第一次握手:主机A发送位码为syn=1,随机产生seqnumber=1234567的数据包到服务器,主机B由SYN=1知道,A要求建立联机;第二次握手:主机B收到请求后要确认联机信息,向A发送acknumber=(主机A的seq+1),syn=1,ack=1,随机产生seq=7654321的包第三次握手:主机A收到后检查acknumber是否正确,即第一次发送的seqnumber+1,以及位码ack是否为1,若正确,主机A会再发送acknumber=(主机B的seq+1),ack=1,主机B收到后确认seq值与ack=1则连接建立成功。完成三次握手,主机A与主机B开始传送数据。

在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。

第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。完成三次握手,客户端与服务器开始传送数据.实例:IP16.3337>23.7788:S3626544836:3626544836

IP23.7788>16.3337:S1739326486:1739326486ack3626544837

IP16.3337>23.7788:ack1739326487,ack1第一次握手:16发送位码syn=1,随机产生seqnumber=3626544836的数据包到23,23由SYN=1知道16要求建立联机;第二次握手:23收到请求后要确认联机信息,向16发送acknumber=3626544837,syn=1,ack=1,随机产生seq=1739326486的包;第三次握手:16收到后检查acknumber是否正确,即第一次发送的seqnumber+1,以及位码ack是否为1,若正确,16会再发送acknumber=1739326487,ack=1,23收到后确认seq=seq+1,ack=1则连接建立成功。图解:

一个三次握手的过程(图1,图2)

(图1)

(图2)

第一次握手的标志位(图3)

我们可以看到标志位里面只有个同步位,也就是在做请求(SYN)

(图3)

第二次握手的标志位(图4)

我们可以看到标志位里面有个确认位和同步位,也就是在做应答(SYN+ACK)

(图4)

第三次握手的标志位(图5)

我们可以看到标志位里面只有个确认位,也就是再做再次确认(ACK)

(图5)

一个完整的三次握手也就是请求---应答---再次确认四次分手:由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。(1)客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送(报文段4)。(2)服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(报文段5)。和SYN一样,一个FIN将占用一个序号。(3)服务器B关闭与客户端A的连接,发送一个FIN给客户端A(报文段6)。(4)客户端A发回ACK报文确认,并将确认序号设置为收到序号加1(报文段7)。

1.为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。2.为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?这是因为虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。

EOF(EndOfFile)4.如果要判断一个Socket对象当前是否处于连接状态,可采用以下方式:socket.isConnected()&&!socket.isClosed();5.如果服务器有多个IP地址,我们可以指定其中的一个作为服务器的IP地址:ServerSocket(intport,intbacklog,InetAddressbindAddr)bindAddr参数:指定服务器要绑定的IP地址6.accept方法的调用方式通常为:while(true){Sockets=ss.accept();7.Socket类提供的半关闭方法:publicvoidshutdownInput()throwsIOExceptionpublicvoidshutdownOutput()throwsIOException8.设置该选项:publicvoidsetSoLinger(booleanon,intseconds)读取该选项:publicintgetSoLinger()SO_LINGER选项用来控制Socket关闭时的行为默认on参数值为false,表示调用close方法会立即返回,但底层协议栈会把剩余数据发送完毕,或等待2MSL时间socket.setSoLinger(true,0):执行close()方法时,会立即返回,底层的协议栈也会立即关闭,所有未发送完的剩余数据被丢弃。socket.setSoLinger(true,3600):执行close()方法不会立即返回,而进入阻塞状态,同时,底层的协议栈会尝试发送剩余的数据。只有满足以下两个条件之一,close()方法才返回:底层的协议栈已经发送完所有的剩余数据。设置的时间消耗完,剩余未发送的数据被丢弃。第一次实验实验题目:网络地址编程实验内容:利用InetaAddress的静态函数getAllByName获取新浪网站的地址,并在控制台显示输出配置自己的机器,为自己机器添加多个IP地址;安装IPv6协议编写程序,判断本机的IP地址是IPv4地址还是IPv6地址import.Inet4Address;import.Inet6Address;import.InetAddress;import.UnknownHostException;publicclassMyIPTest{ publicstaticvoidmain(String[]args){ if(args.length==0) return; try{ InetAddressaddress=InetAddress.getByName(args[0]); System.out.println("IP地址:"+address.getHostAddress()); switch(address.getAddress().length){ case4: System.out.println("根据地址长度判断,这个地址是IPv4地址"); break; case16: System.out.println("根据地址长度判断,这个地址是IPv6地址"); break; } if(addressinstanceofInet4Address) System.out.println("根据地址类型判断,这个地址是IPv4地址"); if(addressinstanceofInet6Address) System.out.println("根据地址类型判断,这个地址是IPv6地址"); }catch(UnknownHostExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } }}第二次实验:实验题目:串行网络聊天程序设计实验内容:利用ServerSocket类和Socket类编写客户端和服务器端程序,实现“学舌”网络程序修改“学舌”程序的服务器端,实现服务器端和客户端的串行聊天程序、importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStreamReader;importjava.io.PrintWriter;import.InetSocketAddress;import.Socket;importjava.util.Scanner;publicclassClient{ publicstaticvoidmain(String[]args)throwsIOException{ Sockets=newSocket(); s.bind(null); s.connect(newInetSocketAddress("localhost",8000)); BufferedReaderbf=newBufferedReader(newInputStreamReader(s.getInputStream())); PrintWriterpw=newPrintWriter(s.getOutputStream(),true); Scannerscanner=newScanner(System.in); Stringstr=scanner.nextLine(); while(str!=null){ pw.println(str); if(str.equals("bye"))break; Stringstr1=bf.readLine(); System.out.println("从服务器端收到的信息>"+str1); str=scanner.nextLine(); } s.close(); }}importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStream;importjava.io.InputStreamReader;importjava.io.OutputStream;importjava.io.PrintWriter;import.InetSocketAddress;import.ServerSocket;import.Socket;publicclassServer{ publicstaticfinalintport=8000; publicstaticvoidmain(String[]args)throwsIOException{ ServerSocketss=newServerSocket(); ss.bind(newInetSocketAddress(port)); System.out.println("服务器启动"); while(true){ Sockets=ss.accept(); BufferedReaderbf=newBufferedReader(newInputStreamReader(s.getInputStream())); PrintWriterpw=newPrintWriter(s.getOutputStream(),true); Scannerscanner=newScanner(System.in); Stringstr=bf.readLine(); while(!str.equals("bye")){ System.out.println("接收到信息"+str); Stringmsg=scanner.nextLine(); pw.println(msg); str=bf.readLine(); } s.close(); } //ss.close(); }}第三次实验:实验题目:多线程并行网络聊天程序设计实验内容:复习Java创建线程的两种方式(继承Thread类及实现Runnable接口)改造实验二的程序,使之成为多线程并行的网络聊天程序packagemultithread1;importjava.io.*;import.*;publicclassEchoServer{ publicEchoServer()throwsIOException{ } publicvoidservice(){ } publicstaticvoidmain(Stringargs[])throwsIOException{ ServerSocketserverSocket=newServerSocket(8000); System.out.println("服务器启动"); while(true){ Socketsocket=serverSocket.accept();//接收客户连接 ThreadworkThread=newThread(newHandler(socket));//创建一个工作线程 workThread.start();//启动工作线程 } }}classHandlerimplementsRunnable{ privateSocketsocket; publicHandler(Socketsocket){ this.socket=socket; } publicvoidrun(){ try{ System.out.println("接受一个新的连接请求" +socket.getInetAddress()+":"+socket.getPort()); BufferedReaderbr=newBufferedReader(newInputStreamReader(socket.getInputStream())); PrintWriterpw=newPrintWriter(socket.getOutputStream(),true); Stringmsg=null; while((msg=br.readLine())!=null){ System.out.println(msg); pw.println("echo:"+msg); if(msg.equals("bye")) break; } }catch(IOExceptione){ e.printStackTrace(); }finally{ try{ if(socket!=null) socket.close(); }catch(IOExceptione){ e.printStackTrace(); } } }}第四次实验:实验题目:非阻塞网络聊天程序设计实验内容:熟悉非阻塞编程中需要使用的四个通信类和两个辅助类编写非阻塞模式的客户端和服务器端程序,实现非阻塞的网络聊天packagenonblock;importjava.io.*;importjava.nio.*;importjava.nio.channels.*;importjava.nio.charset.*;import.*;importjava.util.*;publicclassEchoServer{privateSelectorselector=null;privateServerSocketChannelserverSocketChannel=null;privateintport=8000;privateCharsetcharset=Charset.forName("GBK");publicEchoServer()throwsIOException{selector=Selector.open();serverSocketChannel=ServerSocketChannel.open();serverSocketChannel.socket().setReuseAddress(true);serverSocketChannel.configureBlocking(false);serverSocketChannel.socket().bind(newInetSocketAddress(port));System.out.println("服务器启动");}publicvoidservice()throwsIOException{serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);while(selector.select()>0){SetreadyKeys=selector.selectedKeys();Iteratorit=readyKeys.iterator();while(it.hasNext()){SelectionKeykey=null;try{key=(SelectionKey)it.next();it.remove();if(key.isAcceptable()){ServerSocketChannelssc=(ServerSocketChannel)key.channel();SocketChannelsocketChannel=(SocketChannel)ssc.accept();System.out.println("接收到客户连接,来自:"+socketChannel.socket().getInetAddress()+":"+socketChannel.socket().getPort());socketChannel.configureBlocking(false);ByteBufferbuffer=ByteBuffer.allocate(1024);socketChannel.register(selector,SelectionKey.OP_READ|SelectionKey.OP_WRITE,buffer);}if(key.isReadable()){receive(key);}if(key.isWritable()){send(key);}}catch(IOExceptione){e.printStackTrace();try{if(key!=null){key.cancel();key.channel().close();}}catch(Exceptionex){e.printStackTrace();}}}//#while}//#while}publicvoidsend(SelectionKeykey)throwsIOException{ByteBufferbuffer=(ByteBuffer)key.attachment();SocketChannelsocketChannel=(SocketChannel)key.channel();buffer.flip();//把极限设为位置,把位置设为0Stringdata=decode(buffer);//读取0-limit,p指针变为limitif(data.indexOf("\r\n")==-1)return;StringoutputData=data.substring(0,data.indexOf("\n")+1);System.out.print(outputData);ByteBufferoutputBuffer=encode("echo:"+outputData);while(outputBuffer.hasRemaining())socketChannel.write(outputBuffer);ByteBuffertemp=encode(outputData);buffer.position(temp.limit());pact();if(outputData.equals("bye\r\n")){key.cancel();socketChannel.close();System.out.println("关闭与客户的连接");}}publicvoidreceive(SelectionKeykey)throwsIOException{ByteBufferbuffer=(ByteBuffer)key.attachment();SocketChannelsocketChannel=(SocketChannel)key.channel();ByteBufferreadBuff=ByteBuffer.allocate(32);socketChannel.read(readBuff);readBuff.flip();buffer.limit(buffer.capacity());buffer.put(readBuff);//参数是一个Buffer,将参数buffer中p到limit之间的数据拷贝到调用缓冲区中}publicStringdecode(ByteBufferbuffer){//解码CharBuffercharBuffer=charset.decode(buffer);returncharBuffer.toString(); }publicByteBufferencode(Stringstr){//编码returncharset.encode(str);}publicstaticvoidmain(Stringargs[])throwsException{EchoServerserver=newEchoServer();server.service();}}第五次实验:实验题目:UDP网络聊天程序实验内容:熟悉UDP编程使用的DatagramPackage类和DatagramSocket类编写简单的使用UDP协议进行网络聊天的程序import.*;importjava.io.*;publicclassEchoClient{privateStringremoteHost="localhost";privateintremotePort=8000;privateDatagramSocketsocket;publicEchoClient()throwsIOException{socket=newDatagramSocket();//与本地的任意一个UDP端口绑定}publicstaticvoidmain(Stringargs[])throwsIOException{newEchoClient().talk();}publicvoidtalk()throwsIOException{try{InetAddressremoteIP=InetAddress.getByName(remoteHost);BufferedReaderlocalReader=newBufferedReader(newInputStreamReader(System.in));Stringmsg=null;while((msg=localReader.readLine())!=null){byte[]outputData=msg.getBytes();DatagramPacketoutputPacket=newDa

温馨提示

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

评论

0/150

提交评论