黑马程序员_java网络编程

  -------android培训java培训、期待与您交流! ----------


 

 

 TCP、UDP协议简介绍:
TCP是Tranfer Control Protocol的简称,是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的数据流。发送方和接收方的成对的两个socket之间必须建立连接,以便在TCP协议的基础上进行通信,当一个socket(通常都是server socket)等待建立连接时,另一个socket可以要求进行连接,一旦这两socket连接起来,它们就可以进行双向数据传输,双方都可以进行发送或接收操作。


UDP是User Datagram Protocol的简称,是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。

 

下面对这两种协议做简单比较:

使用UDP时,每个数据报中都给出了完整的地址信息,因此无需要建立发送方和接收方的连接。对于TCP协议,由于它是一个面向连接的协议,在socket之间进行数据传输之前必然要建立连接,所以在TCP中多了一个连接建立的时间。使用UDP传输数据时是有大小限制的,每个被传输的数据报必须限定在64KB之内。而TCP没有这方面的限制,一

旦连接建立起来,双方的socket就可以按统一的格式传输大量的数据。UDP是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方。而TCP是一个可靠的协议,它确保接收方完全正确地获取发送方所发送的全数据。

 

小结:
TCP,可靠,传输大小无限制,但是需要连接建立时间,差错控制开销大。

UDP,不可靠,差错控制开销较小,传输大小限制在64K以下,不需要建立连接。


基于TCP/IP的网络编程:
java在包java.net中提供了两个类Socket和ServerSocket,分别用来表示双向连接的客户端和服务端。例如:
  客户端:Socket client = new Socket("127.0.01.", 80);
  服务端:ServerSocket server = new ServerSocket(80);

下面给出一个用Socket实现的客户和服务器交互的演示程序。


1. 客户端程序
 

 import java.io.*;
  import java.net.*;
  public class TalkClient {
    public static void main(String args[]) {
      try{
        Socket socket=new Socket("127.0.0.1",4700); //向本机的4700端口发出客户请求

        BufferedReader sin=new BufferedReader(new InputStreamReader(System.in)); //由系统标准输入设备构造BufferedReader对象

                                PrintWriter os=new PrintWriter(socket.getOutputStream()); //由Socket对象得到输出流,并构造PrintWriter对象

                                BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));//由Socket对象得到输入流,并构造相应的BufferedReader对象

                                String readline;

                                readline=sin.readLine(); //从系统标准输入读入一字符串

                                while(!readline.equals("bye")){  //若从标准输入读入的字符串为 "bye"则停止循环

                                os.println(readline);//将从系统标准输入读入的字符串输出到Server

                                os.flush(); //刷新输出流,使Server马上收到该字符串

                                 System.out.println("Client:"+readline); //在系统标准输出上打印读入的字符串

                                 System.out.println("Server:"+is.readLine()); //从Server读入一字符串,并打印到标准输出上

                                readline=sin.readLine(); //从系统标准输入读入一字符串

        } //继续循环
        os.close(); //关闭Socket输出流

        is.close(); //关闭Socket输入流

        socket.close(); //关闭Socket

      }catch(Exception e) {

        System.out.println("Error"+e); //出错,则打印出错信息
      }
  }
}


 

2. 服务器端程序
  

import java.io.*;
  import java.net.*;
  import java.applet.Applet;
  public class TalkServer{
    public static void main(String args[]) {
      try{
        ServerSocket server=null;

        try{ 
          server=new ServerSocket(4700); //创建一个ServerSocket在端口4700监听客户请求

        }catch(Exception e) {

          System.out.println("can not listen to:"+e); //出错,打印出错信息
        }
        Socket socket=null;
        try{
          socket=server.accept(); //使用accept()阻塞等待客户请求,有客户

        }catch(Exception e) {

          System.out.println("Error."+e); //出错,打印出错信息
        }

        String line;

        BufferedReader is=new BufferedReader(new InputStreamReader(socket.getInputStream()));//由Socket对象得到输入流,并构造相应的BufferedReader对象

        PrintWriter os=newPrintWriter(socket.getOutputStream());//由Socket对象得到输出流,并构造PrintWriter对象

        BufferedReader sin=new BufferedReader(new InputStreamReader(System.in));//由系统标准输入设备构造BufferedReader对象

        System.out.println("Client:"+is.readLine());  //在标准输出上打印从客户端读入的字符串

        line=sin.readLine();  //从标准输入读入一字符串

        while(!line.equals("bye")){ 

          os.println(line); //向客户端输出该字符串

          os.flush(); //刷新输出流,使Client马上收到该字符串

          System.out.println("Server:"+line); //在系统标准输出上打印读入的字符串

          System.out.println("Client:"+is.readLine()); //从Client读入一字符串,并打印到标准输出上

          line=sin.readLine(); //从系统标准输入读入一字符串

        }  //继续循环

        os.close(); //关闭Socket输出流

        is.close(); //关闭Socket输入流

        socket.close(); //关闭Socket

        server.close(); //关闭ServerSocket

      }catch(Exception e){

        System.out.println("Error:"+e); //出错,打印出错信息
      }
    }
  }


利用多线程实现多客户机制实现在服务器方给 多个客户 提供服务的功能,对上面的程序进行改造如下:

ServerSocket serverSocket=null;

    boolean listening=true;

    try{

      serverSocket=new ServerSocket(4700);  //创建一个ServerSocket在端口4700监听客户请求

    }catch(IOException e) {  }

    while(listening){ //永远循环监听

      new ServerThread(serverSocket.accept(),clientnum).start();//监听到客户请求,根据得到的Socket对象和客户计数创建服务线程,并启动之

      clientnum++; //增加客户计数
    }
    serverSocket.close(); //关闭ServerSocket



//设计ServerThread类

 public class ServerThread extends Thread{

   Socket socket=null; //保存与本线程相关的Socket对象

   int clientnum; //保存本进程的客户计数

   public ServerThread(Socket socket,int num) { //构造函数

    this.socket=socket; //初始化socket变量

    clientnum=num+1; //初始化clientnum变量
   }
   public void run() { //线程主体

    try{
                       //在这里实现数据的接受和发送
                  }
          }

}


 

 

包java.net中提供了两个类DatagramSocket和DatagramPacket用来支持数据报通信,DatagramSocket用于在程序之间建立传送数据报的通信连接, DatagramPacket则用来表示一个数据报。用数据报方式编写client/server程序时,无论在客户方还是服务方,首先都要建立一个DatagramSocket对象,用来接收或发送数据报,然后使用DatagramPacket类对象作为传输数据的载体。下面看一下DatagramPacket的构造方法 :

 

 

     DatagramPacket(byte buf[],int length);  

 DatagramPacket(byte buf[], int length, InetAddress addr, int port);  

 DatagramPacket(byte[] buf, int offset, int length);  

 DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port);  

  其中,buf中存放数据报数据,length为数据报中数据的长度,addr和port旨明目的地址,offset指明了数据报的位移量。

 

 

     在接收数据前,应该采用上面的第一种方法生成一个DatagramPacket对象,给出接收数据的缓冲区及其长度。然后调用DatagramSocket 的方法receive()等待数据报的到来,receive()将一直等待,直到收到一个数据报为止。 

 DatagramPacket packet=new DatagramPacket(buf, 256);  

    Socket.receive (packet);  

 

       发送数据前,也要先生成一个新的DatagramPacket对象,这时要使用上面的第二种构造方法,在给出存放发送数据的缓冲区的同时,还要给出完整的目的地址,包括IP地址和端口号。发送数据是通过DatagramSocket的方法send()实现的,send()根据数据报的目的地址来寻径,以传递数据报。 

 DatagramPacket packet=new DatagramPacket(buf, length, address, port);  

    Socket.send(packet);

 

 

基于URL网络编程:

URL(Uniform Resource Locator)是一致资源定位器的简称,它表示Internet上某一资源的地址。通过URL我们可以访问Internet上的各种网络资源,比如最常见的WWW,FTP站点。浏览器通过解析给定的URL可以在网络上查找相应的文件或其他资源。URL有以下及部分组成,协议名://机器名+端口号+文件名,协议名指明获取资源所使用的传输协议,如http、ftp、gopher、file等

 

为了表示URL, java.net中实现了类URL。我们可以通过下面的构造方法来初始化一个URL对象:

  (1) public URL (String spec);通过一个表示URL地址的字符串可以构造一个URL对象。     

                  URL url=new URL("http://www. baidu.com/")

  (2) public URL(URL context, String spec); 通过基URL和相对URL构造一个URL对象。   

                URL url=new URL(new URL("http://www. baidu.com/"), "index.html")

  (3) public URL(String protocol, String host, String file);    

               new URL("http", "www.XXX.com", "/index.php");

  (4) public URL(String protocol, String host, int port, String file);    

               URL gamelan=new URL("http", "www.XXX.com", 80, "/index.php");

 

 

当我们得到一个URL对象后,就可以通过它读取指定的WWW资源。这时我们将使用URL的方法openStream(),方法openSteam()与指定的URL建立连接并返回InputStream类的对象以从这一连接中读取数据。代码如下:

public class URLReader {

  public static void main(String[] args) throws Exception { 
                      //声明抛出所有例外
    URL tirc = new URL("http://www.XXX.com/");
                      //构建一URL对象
    BufferedReader in = new BufferedReader(new InputStreamReader(tirc.openStream())); //使用openStream得到一输入流并由此构造一个BufferedReader对象

    String inputLine;

    while ((inputLine = in.readLine()) != null) //从输入流不断的读数据,直到读完为止

       System.out.println(inputLine); //把读入的数据打印到屏幕上

    in.close(); //关闭输入流
  }
}


通过URL的方法openStream(),我们只能从网络上读取数据,如果我们同时还想输出数据,例如向服务器端发送一些数据,我们必须先与URL建立连接,然后才能对其进行读写,这时就要用到类URLConnection了。

类URLConnection也在包java.net中定义,它表示Java程序和URL在网络上的通信连接。当与一个URL建立连接时,首先要在一个URL对象上通过方法openConnection()生成对应的URLConnection对象。类URLConnection提供了很多方法来设置或获取连接参数,程序设计时最常使用的是getInputStream()和getOurputStream(),其定义为:


     InputSteram       getInputSteram();

     OutputSteram    getOutputStream();

 

 

 

  通过返回的输入/输出流我们可以与远程对象进行通信。代码如下:

 

  URL url =new URL ("http://www.XXX.com"); //创建一URL对象

  URLConnectin con=url.openConnection(); //由URL对象获取URLConnection对象

  DataInputStream dis=new DataInputStream (con.getInputSteam()); //由URLConnection获取输入流,并构造DataInputStream对象

  PrintStream ps=new PrintSteam(con.getOutupSteam());//由URLConnection获取输出流,并构造PrintStream对象

  String line=dis.readLine(); //从服务器读入一行

  ps.println("client…"); //向服务器写出字符串 "client…"

 

 

 

 

------- android培训java培训、期待与您交流! ----------  详细请查看:http://edu.csdn.net/heima/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值