`
kree
  • 浏览: 127264 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

利用Java实现网络通信以及四层模型

阅读更多

计算机通过TCP/UDP协议在网络上通信是建立在以下四层模型之上的:


  当我们编写JAVA应用程序时,主要是在第四层即应用层工作。一般说来,不必关心TCP/UDP层,这是因为java.net包已提供了系统无关的底层实现。然而,理解TCP和UDP对于决定选择使用哪种java类,还是十分必要的。
  TCP协议是以连接为基础的协议,通信前,首先要建立连接,然后才能通信。因此,能保证同步、准确地进行通信。如果应用程序需要可靠的点对点通信,一般采用TCP这种协议。比如:HTTP,ftp,telnet等应用程序,确保其可靠性对于程序运行是非常关键的。另一方面,有的应用程序对通信的要求并不一定要求如此严格。比如ping命令。我们还可以考虑这样一个例子:服务器提供一个时钟服务,它定时发送时间数据;客户端不断提取时间数据;如果对这样一个应用程序,我们也建立可靠的连接,那么,如果一个数据包丢失,客户请求重发该包,重发回的数据已失去意义了。因此,降低了该服务程序的效率和适用性。
  最后,我们阐述以下另一个较重要的概念:端口。我们知道,数据通过网络到达一台主机(或准确的说是主机的网卡)是通过IP地址实现的。但当该主机运行多个程序时如何识别数据是属于哪个程序的呢?这就是端口。一个端口只能绑定一个应用程序。通过TCP/UDP通信的应用程序必须知道对方的IP地址和端口号才能通信。端口号可取从0-65535,其中,0-1023为保留端口,提供给众所周知的一些服务。下图说明了端口的使用。


  下面,我们具体分析两个java程序,加深对上面概念的理解。

一、 socket和TCP

  下面列出服务程序和客户程序的源代码。具体分析见代码中的注释。
  该程序只能建立单一的一对连接,但根据其原理,可以编写出多线程的多对连接的复杂的网络程序。该应用的客户端程序是一个独立的应用程序,但其完全可以通过Applet来实现相同的功能。
  笔者在IE4.0的环境下,通过关闭一些安全选项实现了浏览器内的Applet与服务器程序的轻松通讯。然而,在IE5.0的环境中,情况发生了变化。IE5.0的安全选项与IE4.0有一定区别。无论如何设置,都无法实现在IE4.0中的效果,显示出了”xxx.xxx.xxx.xxx:4444 can not access”这样的出错信息。通过分析,我认为,这可能是IE5.0对网络安全性的考虑加强的缘故。通过分析,我认为applet程序只应与其所在服务器上的应用程序通讯,且该服务器应该是WEB服务器。于是,我把本应用程序的服务器程序放在WEB SERVER上运行,结果获得了成功。我使用的环境是,WEB SERVER:IIS (Option pack 3);MS VJ++6.0。

//下面KKState类实现一个有趣的对话过程的主要流程:用户启动服务程序,服务程序监听来自网络的连接请求,

//如果有客户连接,则建立连接。然后,在客户终端示″knock!knock!″,客户端如″Who′s there?″,

//则回答″Turnip″。客户输入″Turnip who?″,回答″Turnip the heat,it′s cold in here! Want another?(y/n)″。

//如果客户输入″y″,则进行下一轮新的对话,否则结束。关于对话的内容事先存储在两个字符串数组中。

 

import java.net.*;
import java.io.*;
class KKState{
  private static final int WAITING=0;
  private static final int SENTKNOCKKNOCK=1;
  private static final int SENTCLUE=2;
  private static final int ANOTHER=3;
  private static final int NUMJOKES=5;
  private int state=WAITING;
  private int currentJoke=0;
  private Stringclues={″Tumip″,″Little Old Lady″,″Atch″,″Who″;″Who″};
  private Stringanswers={″Turnip the heat,it′s cold in here!″,
     ″I didn′t know you could yodel!″,
     ″Bless you!″,
     ″Is there an owl in here?″,
     ″Is there an echo in here?″};
String processInput(String theInput){
String theOutput=null;
if(state==WAITING){
   theOutput=″Knock!Knock!″;
   state=SENTKNOCKKNOCK;
  } else if(state==SENTKNOCKKNOCK){
   if(theInput.equalsIgnoreCase(″Who′s there?″)){
    theOutput=clues[currentJoke];
    state=SENTCLUE;
  } else{
    theOutput=″You′re supposed to say\″Who′s there?\″!Try again.Knock!Knock!″;
   }
  }else if(state==SENTCLUE){
     if(theInput.equalsIgnoreCase(clues[currentJoke]+″who?″)){
     theOutput=answers[currentJoke]+″Want another?(y/n)″;
     state=ANOTHER;
   } else{
     theOutput=″You′re supposed to say\″″+clues[currentJoke]+″who?\″″+″!Try again.Knock!Knock!″;
   state=SENTKNOCKKNOCK;
   }
  } else if(state==ANOTHER){
   if(theInput.equalsIgnoreCase(″y″)){
    theOutput=″Knock!Knock!″;
    if(currentJoke==(NUMJOKES-1))
       currentJoke=0
    else
     currentJoke++;
    state=SENTKNOCKKNOCK;
   } else{
    theOutput=″Bye.″;
   state=WAITING;
   }
  }
  return theOutput;
 }
}
//服务器程序
class KnockKnockServer{
public static void main(String[]args){
   ServerSocket serverSocket=null;
   try {
      serverSocket=new ServerSocket(4444);// 创建服务器端socket
   }catch(IOException e){
   System.out.println(″Could not listen on port:″+4444+″,″+e;
   System.exit(1);
   }
  Socket clientSocket=null;
  try{
  clientSocket=serverSocket.accept();//监听申请连接到该socket的要求并建立连接
  }catch(IOException e){
  System.out.println(″Accept failed:″+4444+″,″+e);
  System.exit(1);
  }
  try{
  //通过客户端socket,获取输入数据流对象,通过它可以读入客户端输入的信息
  //通过客户端socket,获取输出数据流对象,通过它可以向客户端输入的信息
  DataInputStream is=new DataInputStream(new BufferedInputStream(clientSocket.getInputStream()));
  PrintStream os=new PrintStream(new BufferedOutputStream(clientSocket.getOutputStream(),1024),false);
  //KKState类用于处理输入的会话信息,然后返回设定好的回答
  KKState kks=new KKState():
  String inputLine,outputLine;
  outputLine=kks.processInput(null);
  os.println(outputLine);//第一次运行,输入参数为null,kks返回:″Knock!Knock!″;然后向客户端写入。
  0s.flush();
  //如果客户端没有输入,readLine将阻塞;如果客户端关闭,readLine返回为null。
  //在下面循环语句中,以读一行,再写一行的方式与客户交互。
  while((inputLine=is.readLine())!=null){
  outputLine=kks.processInput(inputLine);
     os.println(outputLine);
     os.flush();
     if(outputLine.equals(″Bye.″))break;
  }
  //以下完成清除工作。
  os.close();
  is.close();
  clientSocket.close();
  serverSocket.close();
  } catch(IOException e){
  e.printStackTrace();
  }
}
}

 

//客户端程序
import java.io.*;
import java.net.*;
public class EchoTest{
  public static void main(Stringargs){
  Socket echoSocket=null;
  DataOutputStream os-null;
  DataInputsStream is=null;
  DataInputStream stdIn=new DataInputStream(System.in);
  try{ echoSocket=new Socket(″myHost″,4444);
   os=new DataOutputStream(echoSocket.getOutputStream());
   is=newDataInputStream(echoSocket.getInputStream());
  } catch(UnknownHostException e){
  System.err.println(″Don`t know about host:myHost″);
  } catch(IOException e){
  System.err.println(″Couldn`t get I/O for the connection to:myHost″);
  }
  if(echoSocket!=null && os!=null&& is!=null){
  try{
   String userInput;
    while((userInput=stdin.readLine())!
=null){
   os.writeBytes(userInput);
   os.writeByte(″\n′);
   System.out.println(″echo:″+is.readLine()); }
   os.close();
   is.close();
   echoSocket.close();
   } catch (IOException e){
    System.err.println(″I/O failed on the connection to:myHost″);
   }
  }
}
}

 二、 UDP

  采用UDP方式,和TCP有很大的不同。TCP必须由服务器端创建socket,然后由客户端建立socket向服务器端socket发出连接请求,接着服务器端创建一个与客户端socket对应的socket并通过该socket,获得输入输出流,这样,网络通讯变类似文件I/O的方式,而所有网络通讯的复杂性被socket机制所掩盖了(参见图2);使用UDP的情况则简单一些,在通讯中,客户和服务端都只涉及了两个主要的类:DatagramSocket和DatagramPacket类。DatagramPacket类可以看为是信息的载体,必须为它建立数据缓冲区,从而容纳发送或接受的具体信息;DatagramSocket可以看成是DatagramPacket的发送或接受装置,发送一个Packet必须知道发送的主机地址和端口,接受则只需有一个Packet对象作为容器即可(参见图3)。

//本程序说明:首先服务器端生成DatagramSocket,监听某个端口,准备截获发往该端口的数据报。一旦客户端发送一针对服务器端机器和该端口的数据报,则服务器接收该数据报,从中取得数据报的发送地址和发送端口,并向该发送地址和端口发送一应答报文。报文内容为服务器端的一个文件one-liners.txt中的一行文本,如果,该文件不存在,则发送服务器端的当前时间。

//服务器端程序:
import java.io.*;
import java.net.*;
import java.util.*;
//QuoteServer只是提供服务程序的一个入口,主要的程序流程包含在QuoteServer Thread中。
class QuoteServer{
   public static void main(Stringargs){
   new QuoteServerThread().start();
  }
}
class QuoteServerThread extends Thread{
  private DatagramSocket socket=null;//用于发送和接收数据报
  private DataInputStream qfs=null; //用于读取one-liners.txt文件
  QuoteServerThread(){
   super(″QuoteServer″);
   try{
   socket=new DatagramSocket();
   System.out.println(″QuoteServer listening on port:″+socket.getLocalPort());//显示服务器端DatagramSocket的端口号(供客户端使用)
   } catch(java.net.SocketExceptione){
   System.err.println(″Could not create datagram socket.″);
   }
   this.openInputFile();
  }
  public void run(){
   if(socket==null)returnm;
   while(true){
    try{
    byte[]buf=new byte[256]; //建立内存缓冲区供DatagramPacket使用
    DatagramPacket packet;
    InetAddress address;
   int port;
   String dString=null;
   packet=new DatagramPacket(buf,256);
   socket.receive(packet); //接收发往该地址和端口的数据报
   address=packet.getAddress(); //获取数据报的源发送地址
   port=packet.getPort();获取数据报的源发送端口
   if(qfs==null)
    dString=new Date().toString();
   else
    dString=getNextQuote();
   dString.getBytes(0,dString.length(),buf,0);
   packet=new DatagramPacket(buf,buf.length,address,port);
   socket.send(packet); //发回服务器端响应数据报
   } catch(IOExceptione){
   System.err.println(″IOException:″+e);
   e.printStackTrace();
  }
 }
}
protected void finalize(){
  if(socket!=null){
   socket.close();
   socket=null;
   System.out.println(″Closing datagram socket.″);
  }
}
private void openInputFile(){
  try{
   qfs=new DataInputStream(new FileInputStream(″one-liners.txt″));
  }catch(java.io.FileNotFoundException e){
   System.err.println(″Could not open quote file.Serving time instead.″);
 }
}
private String getNextQuote(){
  String returnValue-null;
  try{
   if((returnValue=qfs.readiine())==null){
   qfs.close();
   this.openInputFile();
   returnValue=qfs.readLine(); //该文件应该至少有一行!
   }
  }catch(IOException e){
    returnValue=″IOException occurred in server.″;
  }
  return returnValue;
}
}

 

//客户端必须输入java QuoteClient主机名 端口号的形式来运行客户程序
import java.io*;
impor tjava.net.*;
impor tjava.util.*;
class QuoteClient{
  public static void main(Stringargs){
   int port;
   InetAddress address;
   DatagramSocket socket=null;
   DatagramPacket packet;
   bytesendBuf=new byte[256];
   if(args.length!=2){
     System.out.println(″Usage:java QuoteClient<hostname> <port#>″);
 return;
}
try{
   socket=new DatagramSocket(); //建立DatagramSocket用于发送数据报
} catch(java.net.SocketException e){
  System.err.println(″Could not create datagram socket.″);
}
if(socket!=null){
  try{
   //发送数据
   por=Integer.parseInt(args[1];
   address=InetAddress.getByName(args[0]);
   packet=new DatagramPacket(sendBuf,256,address,port);
   socket.send(packet);
   //获得应答
   packet=new DatagramPacket(sendBuf,256);
   socket.receive(packet);
   String received=new String(packet.getData(),0);
   System.out.println(″Quote of the Moment:″+received);
   socket.close();
  }catch(IOException e){
   System.err.println(″IOException;″+e);
   e.printStackTrace();
   }
  }
 }
}

 

分享到:
评论

相关推荐

    JAVA上百实例源码以及开源项目

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    JAVA上百实例源码以及开源项目源代码

     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

    java网络编程技术课程设计.doc

    TCP网络通信程序设计与实现 摘要: 目前,基于TCP/IP协议的网络得到了普及和飞速的发展,Windows下的网络程序越来越 显得重要。利用TCP/IP协议提供的编程接口———Socket(套接字)可以开发出TCP/IP应用程 序。正确的...

    java开源包4

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包3

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包11

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包6

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    基于JAVA的模拟ATM系统的设计与实现【文献综述】.pdf

    Java 语言由理解和信奉网络计算梦想的一个小巧而专注的开发组设计的,虽然该语言 最初的实施方案有点缺陷,但为了这个梦想,设计者们很少在技术上妥协,结果诞生了一 种专为以相互通信为主要目的的设备而设计的语言...

    java开源包9

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包101

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包5

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包8

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包10

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包1

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    Java资源包01

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包2

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包7

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    基于SNMP的网络拓扑发现.doc

    基于SNMP的网络拓扑发现 一、 SNMP简介 SNMP(Simple Network Management Protocol,...图3.1说明了SNMP网络管理框架的一般体系结构,它由四个主要部件构成,分别是:通信网络、网络协议、网络管理进程和被管网络实体。

    java 面试题 总结

    但通常情况下,由于Java Bean是被容器所创建(如Tomcat)的,所以Java Bean应具有一个无参的构造器,另外,通常Java Bean还要实现Serializable接口用于实现Bean的持久性。Java Bean实际上相当于微软COM模型中的本地...

Global site tag (gtag.js) - Google Analytics