计算机通过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实现P2P网络通信" 本文将详细介绍如何使用JAVA实现P2P网络通信,分析P2P基本概念及其基本工作原理,并探讨了用JAVA实现p2p网络通信的技术。 一、P2P基本概念 P2P(Peer-to-Peer)模型是与C/S(客户/服务器...
这些内容详细阐述了如何利用Java进行网络通信,包括建立连接、发送和接收数据、处理异常以及优化网络性能。 总的来说,《Java网络编程(第四版)》是一本全面而实用的教程,适合有一定Java基础的开发者学习。它不仅...
- **网络模型**:Java网络编程基于OSI七层模型和TCP/IP四层模型。理解这些模型有助于理解网络通信的基本原理。 - **IP地址与端口号**:IP地址用于标识网络上的设备,端口号则区分同一设备上的不同服务。 2. **...
Telnet协议是一种基于客户端/服务器模型的应用层协议,主要功能是为用户提供一种登录远程主机的方式,并能在不同的操作系统之间进行通信。Telnet协议采用TCP端口号23,默认情况下使用明文传输数据,包括用户名和密码...
在设计原理中,可能包括了网络通信的基础概念,如OSI七层模型和TCP/IP四层模型,以及网络协议,如HTTP、TCP、UDP等。技术选型可能涉及到Java的网络编程API,如Socket、ServerSocket、DatagramSocket等,这些API是...
根据提供的文件信息,本文将对“JAVA源码JAVA网络通信系统的研究与开发(论文+源代码+开题报告)”中的关键技术点进行详细解读,并结合相关内容分析该系统的实现原理及应用场景。 ### 一、项目背景 随着互联网技术的...
在本篇内容中,我们将探讨网络通信的基本概念以及Java如何与Internet交互。 首先,TCP/IP是Internet的主要通信协议,它定义了数据传输的规则。TCP/IP模型包括应用层、传输层、网络层、链路层和物理层。而ISO/OSI...
它详细介绍了如何利用Java语言进行网络通信,涵盖了网络编程的基本概念、协议以及实现方法。 一、Java网络编程基础 在Java中,网络编程主要依赖于Java的Socket和ServerSocket类,它们提供了TCP/IP通信的基础。通过...
1. **网络通信基础**:介绍了网络通信的基本原理,包括OSI七层模型、TCP/IP四层模型,以及各层的主要功能。 2. **Java网络编程**:详细讲解了Java的Socket和ServerSocket类,以及InputStream和OutputStream流如何...
总结,基于Java的网络通讯系统设计与实现涉及到多个层次的知识,包括Java网络API的使用、并发处理、协议理解和实现、异常处理以及安全性保障。通过学习和实践这些知识点,开发者可以构建出功能强大、高效的网络应用...
### Java网络通信:Socket与HTTP详解 在网络编程领域,Java作为一种广泛应用的编程语言,提供了丰富的API来处理网络通信。本文将深入探讨Java网络通信中的两大核心主题:HTTP和Socket通信。 #### 一、网络通信的...
1. **网络通信模型**:介绍TCP/IP协议栈,讲解OSI七层模型或TCP/IP四层模型,以及它们在网络通信中的作用。 2. **Java网络编程基础**:详细解释Socket编程,包括TCP连接的建立、数据的发送和接收、异常处理等。 3. *...
1. **网络编程基础**:介绍网络的基本概念,如OSI七层模型、TCP/IP四层模型,以及它们在网络通信中的作用。还会讲解IP地址、子网掩码、端口号等网络通信的基础元素。 2. **Java网络编程API**:深入解析Java的Socket...
本书详细介绍了如何利用Java API进行网络通信,包括TCP/IP协议、套接字(Socket)编程、HTTP、HTTPS、多线程以及并发处理等核心概念。 在Java网络编程中,理解网络模型的基础至关重要。TCP/IP协议是互联网的基础,由...
网络参考模型通常遵循OSI七层模型或TCP/IP四层模型(有时也扩展为五层模型)。在OSI模型中,数据包从应用层(如HTTP协议)向下经过表示层、会话层、传输层(如TCP)、网络层(如IP)、数据链路层和物理层,最终在...
本课程设计关注于TCP网络通信程序的设计与实现,利用Java语言的网络编程接口,特别是Socket类,来创建C/S(客户端/服务器)模式的应用程序。 首先,TCP/IP协议是互联网的基础,它由网络接口层、网络层、传输层和...
此外,为了深入分析捕获的数据,可能还需要了解网络协议栈的工作原理,如OSI七层模型或TCP/IP四层模型,以及各个层次的主要协议和字段含义。同时,对于网络安全方面的知识,例如端口扫描、DDoS攻击、恶意软件传播等...
学习Java网络编程,需要具备一定的基础知识,如Java语言基础、计算机网络知识,理解OSI七层模型,以及对TCP/IP协议的理解。操作系统、分布式系统和网络计算的背景知识也能帮助更好地设计和实现网络程序。 在网络...
文件“网络抓包原理分析.doc”很可能提供了更深入的理论知识,可能涵盖了网络协议栈的工作原理,数据包是如何在网络中传输的,以及抓包过程中涉及的技术细节,比如TCP/IP四层模型(链路层、网络层、传输层、应用层)...