黑马程序员——Java基础知识——网络编程

来源:互联网 发布:黑客网络hacknet 攻略 编辑:程序博客网 时间:2024/06/05 15:50

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! 

一、概述

         首先通过下面的图例简单演示不同主机的程序之间的数据传输过程:


           在整个信息发送过程中,要找到对方的IP地址,将数据逐层封包,通过主机至网络层发送到对方主机上,然后向上逐层拆包,找到对方的指定应用程序,将数据发到该指定应用程序上。这样信息就在不同主机间发送成功了。整个过程就涉及到了我们要学习的网络通信的重要知识点:网络模型、网络通信要素(IP地址、端口、传输协议)。

          网络模型:有OSI参考模型和TCP/IP参考模型。二者的结构如下图:

 

       我们接下来学习的网络编程都处于传输层和网际层,每一个层都有对应的通信协议。应用层对应的是FTP和HTTP协议,传输层是TCP和UDP,网际层的协议为IP。从上面的QQ发送信息的过程中可以看到,用户在应用层传入数据,经过逐层封包,最后到达主机至网络层发送给另一台主机,然后再逐级向上拆包。

        网络通讯三要素:IP地址、端口、传输协议。

         (1)IP地址:它是网络中的设备标识,可以用主机名来表示,两者存在映射关系。本机的回环地址是:127.0.0.1 (主机名:localhost)。Java中把IP地址封装成了一个InetAddress类,存放在java.net包中。

       通过这个类的方法,可以实现对IP地址、主机名的获得等功能,常用功能如下:

       1.获得该类对象: InetAddress i=InetAddress.getByName(String host);获取指定主机的InetAddress对象,注意最好用IP地址获取,因为主机名需要解析。

                                    InetAddress i=InetAddress.getByName(String host);获取指定主机的所有InetAddress对象,返回一个数组

                                    InetAddress  i=InetAddress.getLocalHost();获取本机的InetAddress对象。

       2.获取IP地址和主机名

                                   i.getHostAddress();返回IP地址字符串(文本形式)。

                                   i.getHostName();返回IP地址对应的主机名。

       注意,通过上面的方法,传入一个指定的主机名,就可以获得它的IP地址对象,获取其具体的一个或多个地址。但如果IP地址和对应的主机名的映射关系在网络上不存在,就会解析失败。

       下面通过一段代码进行演示:

public static void main(String[] args) throws UnknownHostException {//获取sohu的IP地址对象InetAddress[] i=InetAddress.getAllByName("www.sohu.com");//获取具体的IP地址for(InetAddress ia:i)System.out.println(ia.getHostAddress());//获取本机的IP对象,并获取具体IP地址和主机名InetAddress i1=InetAddress.getLocalHost();String name=i1.getHostName();String  ip=i1.getHostAddress();System.out.println(name+":"+ip);}
        (2)端口号:用于标示进程的逻辑地址,不同进程的标识。有效端口的设置范围为0~65535,注意系统会保留0~1024端口。所以设置时要避开。

        (3)传输协议: 就是通讯规则,主要是TCP和UDP协议。下面对这两种协议的特点和应用分别进行介绍:

        UDP协议:面向无连接,不建立连接,将数据及源和目的封装在数据包中来发送,每个数据包的大小限制住在64K以内,因无连接,速度快,但可能出现数据丢失,是不可靠协议。应用于聊天程序、桌面共享、视频会议等。

        TCP协议:面向连接,在建立连接后,形成传输数据的通道,可以进行大数据量的传输。因通过三次握手建立连接,速度稍慢,但能保证数据的安全性,是可靠的协议。应用于下载文件、文件传输等程序中。

         三次握手:第一次本机发送连接请求,第二次对方确认连接,第三次本方再次确认连接成功。

         网络通信的步骤:

         (1)找到IP地址。

         (2)数据要发送到对方的指定应用程序上,这时就要用数字标识该应用程序上,就是用到端口。如果没有定义端口,数据就无法发送到该应用程序上。

         (3)定义通信规则,国际组织定义了通用协议 TCP/IP。

、TCP和UDP传输的建立与应用

       1.Socket:端点,就相当于港口,是网络服务提供的一种机制,通信两端都要有Socket对象,才能建立通信服务。网络通信就是Socket之间的通信,数组在两个Socket之间通过IO传输。

       2.UDP传输

      DatagramSocket类,表示用来发送和接收数据报包的套接字,即Socket;DatagramPacket类,表示数据报包。下面就通过建立这个两个类的对象,调用它们的特有方法,实现数据的UDP传输。具体步骤如下:

       (1)发送端:

            1.通过创建DatagramSocket对象,建立Socket服务。可以指定本程序端口,也可不指定根据系统自动分配。

            2.确定数据,将要发送的数据封装到数据报包DatagramPacket对象中,数据报包对象中还要指定接收数据的主机和端口。

            3.通过Socket服务中的send(DatagramPacket  dp),将数据报包发送出去。

            4.关闭资源。

          如同下面这段代码:

class UDPSend {public static void main(String[] args) throws IOException {   //创建DatagramSocket对象,建立Socket服务,并指定本程序端口。DatagramSocket ds=new DatagramSocket(10000);   //将提供的数据封装成数据报包,并在数据报包中指定要发送到的主机和端口。byte[]by="大河向东流,天上的星星参北斗".getBytes();DatagramPacket dp=new DatagramPacket(by,by.length,InetAddress.getLocalHost(),10001);   //通过send方法,将数据报包发送出去 ds.send(dp);   //关闭资源 ds.close();}}
        (2)接收端:
             1.创建DatagramSocket对象,建立Socket服务,定义时要监听一个端口,就是给应用程序定义数字标识,用来接收发送

给该应用程序的数据。  

               2. 定义数据报包,用来存储接收到的数据,

              3.通过Socket服务中的receive方法,将接收到的数据存入数据报包中。

              4.利用DatagramPacket中的特有功能提取数据信息。

              5.关闭资源。

         具体如下:

 class UDPRec {public static void main(String[] args) throws IOException {//1,创建udp socket,定义一个监听端口。DatagramSocket ds = new DatagramSocket(10001);//2,定义数据包。用于存储数据。byte[] buf = new byte[1024];DatagramPacket dp = new DatagramPacket(buf,buf.length);        //3,通过receive方法将收到数据存入数据包中。ds.receive(dp);//4,通过数据包的方法获取其中的数据。String ip=dp.getAddress().getHostAddress();String data=new String(dp.getData(),0,dp.getLength());int port=dp.getPort();System.out.println(ip+"::"+data+"::"+port);        //5,关闭资源      ds.close();}}
        要注意的是,发送端和接收端是两个独立的程序,定义发送端时,要在数据报包中明确接收数据的主机和端口;定义接收端时要定义一个监听的端口。
       下面利用UDP传输协议的获取键盘录入,发送数据的程序。如下:

//发送端class UDPSend {        public static void main(String[] args) throws IOException  {   //创建DatagramSocket对象,建立Socket服务,并指定本程序端口。DatagramSocket ds=new DatagramSocket(10000);    //建立流对象,与键盘录入相关联,加入缓冲技术BufferedReader br=new BufferedReader(new InputStreamReader(System.in));String line=null;while((line=br.readLine())!=null){       if("over".equals(line))         break;       byte[]by=line.getBytes();       //将获取的数据封装成数据报包,并在数据报包中指定要发送到的主机和端口。       DatagramPacket dp=new DatagramPacket(by,by.length,InetAddress.getLocalHost(),10001);      //通过send方法,将数据报包发送出去   ds.send(dp);}   //关闭资源 ds.close();}}//接收端class UDPRec {       public static void main(String[] args) throws IOException {//1,创建udp socket,定义一个监听端口。DatagramSocket ds = new DatagramSocket(10001);//2,定义数据包。用于存储数据。while(true){   byte[] buf = new byte[1024];  DatagramPacket dp = new DatagramPacket(buf,buf.length);          //3,通过receive方法将收到数据存入数据包中。  ds.receive(dp);  //4,通过数据包的方法获取其中的数据。  String ip=dp.getAddress().getHostAddress();  String data=new String(dp.getData(),0,dp.getLength()); int port=dp.getPort(); System.out.println(ip+"::"+data+"::"+port);}}}
       定义一个聊天程序,实现信息发送和收到的同时运行,这时就需要用到多线程来实现。如下:

class UDPTest { public static void main(String[] args) throws IOException {        //建立DatagramSocket对象 DatagramSocket ds1=new DatagramSocket(); DatagramSocket ds2=new DatagramSocket(10002); //启动程序 new Thread(new SendDemo(ds1)).start(); new Thread(new RecDemo(ds2)).start();}}//定义一个类,表示发送,实现Runnable接口class  SendDemo implements Runnable{    //定义DatagramSocket的引用private DatagramSocket ds;SendDemo(DatagramSocket ds){   this.ds=ds;}//复写run方法,定义要运行的代码public void run(){BufferedReader br=null;try {br=new BufferedReader(new InputStreamReader(System.in));String line=null;//获取键盘录入,封装成数据报包,并发送出去while((line=br.readLine())!=null){if("88".equals(line))break;byte[]by=line.getBytes();DatagramPacket dp=new DatagramPacket(by,by.length,InetAddress.getLocalHost(),10002);ds.send(dp);}//关闭资源ds.close();} catch (Exception e) {throw new RuntimeException("获取键盘录入失败");}}}//定义一个类表示接收,实现Runnable接口class RecDemo implements Runnable{//定义DatagramSocket的引用private DatagramSocket ds;RecDemo(DatagramSocket ds){   this.ds=ds;}//复写run方法,定义要运行的代码public void run(){while(true){  byte[] buf = new byte[1024];  DatagramPacket dp = new DatagramPacket(buf,buf.length);          //通过receive方法将收到数据存入数据包中。  try {ds.receive(dp);} catch (IOException e) {throw new RuntimeException("数据接收失败");} //通过数据包的方法获取其中的数据。  String ip=dp.getAddress().getHostAddress();  String data=new String(dp.getData(),0,dp.getLength());  if("88".equals(data))   break;  int port=dp.getPort();  System.out.println(ip+":"+data);          }       }}

  3.TCP传输:

        使用TCP传输,要建立客户端和服务器端,分别用Socket和ServerSocket的对象表示。建立连接后,通过Socket中的IO流进行数据传输。客户端与服务器端是两个独立的应用程序。Socket对象建立时就可以连接指定的主机,因为TCP是面向连接的,所以在建立Socket服务时,就要有服务器端存在,连接成功,形成通路后,就可以在该通道进行数据传输了。注意,空参数Socket对象可以通过connect方法连接服务器端。设置基本的TCP传输步骤如下:

         (1)服务器端:

                 1.创建SeverSocket对象,建立Socket服务,监听一个端口。

                 2.通过accept方法,获取链接过来的客户端对象。这个方法是阻塞式的,没有连接就会等。

                 3.客户端如果过来数据,那么服务端就使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据。

                 4.关闭服务器(可选操作)。

               如下:

class TCPServer {public static void main(String[] args) throws IOException { //创建ServerSocket对象,建立Socket服务,指定监听端口  ServerSocket  ss=new ServerSocket(10004); while(true){  //获取连接的客户端对象。  Socket s=ss.accept(); //通过获取客户端对象的读取流来读取客户端发送来的数据。  InputStream is=s.getInputStream();  byte[]by=new byte[1024];  int len=is.read(by);  System.out.println(new String(by,0,len)); }}}
    (2)客户端:

          1.建立Socket服务,指定要连接的主机和端口。

          2.获取Socket服务中的输出流,将数据写入到流中,通过网络发送个服务器端。

          3.如果服务器端有反馈信息,获取Socket流中的输入流,获取服务器端反馈的数据信息。

          4.关闭资源。

         如下:

class TCPClient {public static void main(String[] args) throws Exception { //建立Socket服务,指定要连接的主机和端口Socket s=new Socket(InetAddress.getLocalHost(),10004);         //获取输出流,写入数据。OutputStream os=s.getOutputStream();os.write("大河向东流,天上的星星参北斗".getBytes());//关闭资源s.close();}}
   当客户端进行数据传输给服务器端时,数据传输成功后,服务器端一般会有信息反馈给客户端。程序如下:

//定义服务端public class TCPServer {public static void main(String[] args) throws Exception { //创建ServerSocket对象,建立Socket服务,指定监听端口  ServerSocket  ss=new ServerSocket(10004); while(true){  //获取连接的客户端对象。  Socket s=ss.accept(); //通过获取客户端对象的读取流来读取客户端发送来的数据。  InputStream is=s.getInputStream();  byte[]by=new byte[1024];  int len=is.read(by);  System.out.println(new String(by,0,len)); //通过获取客户端对象的输出流给客户端发送反馈信息    OutputStream out = s.getOutputStream();        out.write("数据已接收".getBytes());            s.close();     }}}//定义客户端class TCPClient {public static void main(String[] args) throws Exception { //建立Socket服务,指定要连接的主机和端口Socket s=new Socket(InetAddress.getLocalHost(),10004);         //获取输出流,写入数据。OutputStream os=s.getOutputStream();os.write("大河向东流,天上的星星参北斗".getBytes());//获取输入流,读取服务器端的反馈信息InputStream in = s.getInputStream();        byte[] buf = new byte[1024];        int len = in.read(buf);        System.out.println(new String(buf,0,len));    }}

       下面是一个TCP传输的练习:

/*需求:建立一个文本转换服务器。客户端给服务端发送文本,服务单会将文本转成大写在返回给客户端。而且客户度可以不断的进行文本转换。当客户端输入over时,转换结束。分析:客户端:既然是操作设备上的数据,那么就可以使用io技术,并按照io的操作规律来思考。源:键盘录入。目的:网络设备,网络输出流。而且操作的是文本数据。可以选择字符流。步骤1,建立服务。2,获取键盘录入。3,将数据发给服务端。4,服务端返回大写数据。5,关闭资源。都是文本数据,可以使用字符流进行操作,同时提高效率,加入缓冲。*/import java.io.*;import java.net.*;class  TransClient{public static void main(String[] args) throws Exception{Socket s = new Socket(InetAddress.getLocalHost(),10005);//定义读取键盘数据的流对象。BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));//定义目的,将数据写入到socket输出流。发给服务端。PrintWriter out = new PrintWriter(s.getOutputStream(),true);//定义一个socket读取流,读取服务端返回的大写信息。BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));String line = null;while((line=bufr.readLine())!=null){if("over".equals(line))break;out.println(line);String str =bufIn.readLine();System.out.println(str);}                //关闭资源bufr.close();s.close();}}/*服务端:源:socket读取流。目的:socket输出流。都是文本,装饰。*/class  TransServer{public static void main(String[] args) throws Exception{ServerSocket ss = new ServerSocket(10005);Socket s = ss.accept();String ip = s.getInetAddress().getHostAddress();System.out.println(ip+"....connected");//读取socket读取流中的数据。BufferedReader bufIn =new BufferedReader(new InputStreamReader(s.getInputStream()));//目的。socket输出流。将大写数据写入到socket输出流,并发送给客户端。PrintWriter out = new PrintWriter(s.getOutputStream(),true);String line = null;while((line=bufIn.readLine())!=null){    System.out.println(line);                    out.println(line.toUpperCase());}s.close();ss.close();}}
      在这个程序中加入缓冲技术,提高了程序的运行效率。要注意的是read方法是阻塞式方法,当没有读到数据或没有读到结束标记时两边read方法都会等待。

       通过TCP传输,可以实现不同主机之间的文件拷贝,就是把客户端的文件上传到服务端上,一般上传成功后,服务器端会提示上传成功,如下面的这个程序:

/** 客户端向服务器上传一个文件。上传完毕后,服务器向客户端反馈上传成功。 *///定义客户端class  TextClient{public static void main(String[] args) throws Exception{Socket s = new Socket(InetAddress.getLocalHost(),10006);        //建立读取流,和要上传的文件相关连BufferedReader bufr = new BufferedReader(new FileReader("F:\\123.txt"));        //获取输出流。        PrintWriter out = new PrintWriter(s.getOutputStream(),true);        //实现上传             String line = null;while((line=bufr.readLine())!=null){out.println(line);}//关闭客户端的输出流。相当于给流中加入一个结束标记-1.s.shutdownOutput();        //获取读取流,为了提高效率,加入转换流和缓冲技术BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));        //获取服务器端反馈信息        String str = bufIn.readLine();System.out.println(str);        //关闭资源bufr.close();        s.close();}}//定义服务端class  TextServer{public static void main(String[] args) throws Exception{ServerSocket ss = new ServerSocket(10006);Socket s = ss.accept();String ip = s.getInetAddress().getHostAddress();System.out.println(ip+"....connected");        //获取连接对象的输入流,加入转换流和缓冲技术,提高效率        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));         //定义输出流,指定目的文件        PrintWriter out  = new PrintWriter(new FileWriter("F:\\234.txt"),true);        //接收并输出数据到指定文件String line = null;        while((line=bufIn.readLine())!=null)                 out.println(line);        //给客户端发送反馈信息PrintWriter pw = new PrintWriter(s.getOutputStream(),true);pw.println("上传成功");        //关闭资源        out.close();s.close();ss.close();}}

       在这个程序中,要注意的是在客户端的上传数据上传完毕后,要通过shutdownOutput()方法告诉服务器端,数据已全部上传完毕。否则服务器端一直继续等待客户端上传数据。shutdownOutput()方法,相当于给输出流加了一个结束标记。

       这个程序是单线程的,当一个客户端连接上服务器,被服务器获取到后,其他的客户端就必须等待,而在实际生活中每个服务器都有大量的客户端进行连接,这时为了实现客户端的并发使用服务器,就需要使用多线程技术,将每一个客户端对象都封装在一个线程里,实现客户端的并发使用。下面的程序就是服务器端实现了多线程,客户端可以并发使用,如下:

//将每一个客户端对象封装到线程里class PicThread implements Runnable{private Socket s;PicThread(Socket s){this.s = s;}public void run(){int count = 1;String ip  = s.getInetAddress().getHostAddress();try{System.out.println(ip+"....connected");InputStream in = s.getInputStream();File dir =  new File("d:\\pic");File file = new File(dir,ip+"("+(count)+")"+".jpg");while(file.exists())file = new File(dir,ip+"("+(count++)+")"+".jpg");FileOutputStream fos = new FileOutputStream(file);byte[] buf = new byte[1024];int len = 0;while((len=in.read(buf))!=-1){fos.write(buf,0,len);}OutputStream out = s.getOutputStream();out.write("上传成功".getBytes());fos.close();s.close();}catch (Exception e){throw new RuntimeException(ip+"上传失败");}}}class  PicServer{public static void main(String[] args) throws Exception{ServerSocket ss = new ServerSocket(10007);//多个客户端可以同时访问                 while(true){Socket s = ss.accept();new Thread(new PicThread(s)).start();}}}

下面是一个登陆服务器端的程序:

/*客户端通过键盘录入用户名。服务端对这个用户名进行校验。如果该用户存在,在服务端显示xxx,已登陆。并在客户端显示 xxx,欢迎光临。如果该用户存在,在服务端显示xxx,尝试登陆。并在客户端显示 xxx,该用户不存在。最多就登录三次。*/import java.io.*;import java.net.*;//定义客户端class  LoginClient{public static void main(String[] args) throws Exception{Socket s = new Socket(InetAddress.getLocalHost(),10008);        //建立流对象,获取键盘录入,加入缓冲BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));        //获取Socket输出流PrintWriter out = new PrintWriter(s.getOutputStream(),true);        //获取Socket输入流,加入缓冲BufferedReader bufIn =new BufferedReader(new InputStreamReader(s.getInputStream()));         //限定登陆次数for(int x=0; x<3; x++){String line = bufr.readLine();            //不再输入,循环结束if(line==null)break;out.println(line);            //获取服务端反馈String info = bufIn.readLine();System.out.println("info:"+info);        //登陆成功,结束            if(info.contains("欢迎"))break;}        //关闭资源bufr.close();s.close();}}//定义客户端线程class UserThread implements Runnable{private Socket s;UserThread(Socket s){this.s = s;}public void run(){String ip = s.getInetAddress().getHostAddress();try  {   //限制登陆次数for(int x=0; x<3; x++){    BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));                //读取用户传入的登陆名String name = bufIn.readLine();//用户不再输入,循环结束if(name==null)break;                //建立流对象,与登录名列表的文件相关联BufferedReader bufr = new BufferedReader(new FileReader("F:\\list.txt"));PrintWriter out = new PrintWriter(s.getOutputStream(),true);String line = null;                //定义判断标识boolean flag = false;while((line=bufr.readLine())!=null){  //查询用户名是否存在  if(line.equals(name)){flag = true;break;}}//登陆成功if(flag){System.out.println(name+",已登录");out.println(name+",欢迎光临");break;}//登陆失败                else{System.out.println(name+",尝试登录");out.println(name+",用户名不存在");}}s.close();}catch (Exception e){throw new RuntimeException(ip+"校验失败");}}}class  LoginServer{public static void main(String[] args) throws Exception{ServerSocket ss = new ServerSocket(10008);//客户端可并发访问         while(true)  {Socket s = ss.accept();new Thread(new UserThread(s)).start(); }}}

三、浏览器和Tomcat服务器

          浏览器就是最常见的客户端,它能够对html代码进行解析。下面自定义一个服务器,通过浏览器对其进行访问。程序如下:

public static void main(String[] args) throws Exception {//建立ServerSocket对象,创建Socket服务         ServerSocket ss=new ServerSocket(10009);        //获取连接客户端对象         Socket s=ss.accept();        //获取Socket服务的输出流。           PrintWriter pw=new PrintWriter(s.getOutputStream(),true);        //输出数据         pw.println("<font color='black' size='8'>欢迎光临服务器</font>");        //关闭资源         s.close();         ss.close();}
   在浏览器输入IP地址和端口号,就能看到服务端的输出数据。效果如下:


         还可以通过浏览器访问Tomcat服务器,Tomcat是常用的一种服务器,它内部封装了ServerSocket对象,可以读取自定义的资源。可以把自定义的资源存储在Tomcat目录中的myweb目录里。下面我们就通过定义程序,模拟浏览器,访问Tomcat服务器,获取数据。这时就需要通过向Tomcat发送http请求消息头,来获取资源。如下:

  public static void main(String[] args)throws Exception {   //建立Socket对象,创建Socket服务Socket s = new Socket("192.168.1.113",8080);//获取输出流PrintWriter out = new PrintWriter(s.getOutputStream(),true);        //发送请求消息头out.println("GET /myweb/2.html HTTP/1.1");//请求获取指定资源路径下的资源out.println("Accept: */*");//可以接收所有数据类型out.println("Accept-Language: zh-cn");//接收语言out.println("Host: 192.168.1.113:8080");//明确IP地址和端口out.println("Connection: Keep-Alive");//连接状态        //请求消息头必须和消息体有空行。out.println();out.println();        //获取输入流BufferedReader bufr = new BufferedReader(new InputStreamReader(s.getInputStream()));String line = null;          while((line=bufr.readLine())!=null){System.out.println(line);}        //关闭资源s.close();      }}

       要注意的请求消息头和请求消息之间一定要用空行隔开。接下来我们再结合图形化界面,创建一个简易的浏览器,因为要获取输入的指定IP地址、主机名、端口等,这时就要用到URL对象,URL代表一个统一资源定位符,内部带有协议的封装了Socket对象,通过其特有方法获取I要连接的服务器端,通过openConnection方法与服务器端建立连接。下面就通过URL对象,实现浏览器的创建和功能实现。如下:

class  IEDemo{//定义组件引用        private Frame f;private TextField tf;private Button but;private TextArea ta;private Dialog d;private Label lab;private Button okBut;IEDemo(){init();}public void init(){//窗体的创建、基本设置                f = new Frame("my window");f.setBounds(300,100,600,500);f.setLayout(new FlowLayout());tf = new TextField(60);but = new Button("转到");ta = new TextArea(25,70);d = new Dialog(f,"提示信息-self",true);d.setBounds(400,200,240,150);d.setLayout(new FlowLayout());lab = new Label();okBut = new Button("确定");d.add(lab);d.add(okBut);f.add(tf);f.add(but);f.add(ta);                //加载事件myEvent();f.setVisible(true);}private void  myEvent(){                okBut.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e){d.setVisible(false);}});d.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent e){d.setVisible(false);}});                //文本框添加键盘监听tf.addKeyListener(new KeyAdapter(){public void keyPressed(KeyEvent e){try{if(e.getKeyCode()==KeyEvent.VK_ENTER)showDir();}catch (Exception ex){throw new RuntimeException("操作失败");                                }}});                //按钮添加活动监听but.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e){try{showDir();}catch (Exception ex){  throw new RuntimeException("操作失败");}}});                  f.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent e){System.exit(0);}});}        //定义连接客户端的方法private void showDir()throws Exception{ta.setText("");                         String urlPath = tf.getText();//建立URL对象                URL url = new URL(urlPath);//实现连接                URLConnection conn = url.openConnection();//获取输入流InputStream in = conn.getInputStream();byte[] buf = new byte[1024];int len = in.read(buf);                //将数据写入文本区ta.setText(new String(buf,0,len));}public static void main(String[] args) {new IEDemo();}}
    注意一般输入网址,是不带端口号的,此时通过URL的getPort()获取。若通过网址返回的port为-1,则分配一个默认的80端口

小知识点:

        1.当Socket对象中构造函数为空时,可以通过connect方法连接服务器。

        2.ServerSocket(int port ,int backlog ),backlog表示队列的最大长度,即最多有几个客户端。通过这个构造函数,对客户端数量进行限制。

       3.我们上网时输入的都是网址,而不是ip地址,是怎么连接到指定主机的呢?这时就需要域名解析(DNS),将主机名变成IP地址。我们访问一个网址的过程是这样的:我们在进行访问时,会现在本机的hosts文件中寻找对应映射,有的话就直接返回。没有,就到DNS中去找对应的映射,找打后返回对应的IP地址,再通过IP地址找到对应的服务器。


-------------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

0 0