首页 > 代码库 > 黑马程序员_Java网络编程

黑马程序员_Java网络编程

1,IP地址和InetAddress

IP地址是互联网上每台计算机都有的自己的标记,IP地址分为5类,A类保留给政府,B类给中等规模的公司,C类给任何需要的人,D类用于组播,E类用于实验.

A类  1.0.0.1-126.255.255.254  B类  128.0.0.1-191.255.255.254   C类  192.0.0.1-223.255.255.254  D类 244.0.0.1-239.255.255.254

E类 240.0.0.1-255.255.255.254

在以后开发的时候,经常使用的127.0.0.1表示的是本机的IP地址

InetAddress

该类主要表示的是IP地址,有两个子类,Inet4Address和Inet6Address

该类没有构造函数,但是有提供了静态的方法去获得该类的对象

1

我们去获取本家的IP地址等一些信息的时候,先通过该类的静态方法去得到一个InetAddress的对象,有了对象后,通过该类中的各种方法,去获取相信的信息,比如需要打印出IP地址的话,使用的肯定是返回值为String的方法.

package cn.wjd.ip;import java.net.InetAddress;public class IPDemo {    public static void main(String[] args) throws Exception {        //获取本地地址IP对象        InetAddress ip = InetAddress.getLocalHost();        ip = InetAddress.getByName("www.baidu.com");//本地DNS   hosts        System.out.println(ip.getHostAddress());        System.out.println(ip.getHostName());    }}

2,UDP程序设计

UDP是不可靠的连接协议,这种协议在各种聊天工具中被广泛的使用,在java中使用DatagramSocket来完成对信息的发送,使用DatagramPacket来包装一条需要发送的信息

package cn.net;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.LineNumberReader;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.UnknownHostException;public class Send implements Runnable {    // 创建UDP的Socket流对象    private DatagramSocket ds = null;    public Send(DatagramSocket ds) {        super();        this.ds = ds;    }    public void run() {        try {            BufferedReader bufr = new BufferedReader(new InputStreamReader(                    System.in));            String line = null;            while ((line = bufr.readLine()) != null) {                byte[] buf = line.getBytes();                DatagramPacket dp = new DatagramPacket(buf, buf.length,                        InetAddress.getByName("wjd"), 9999);                ds.send(dp);                if("88".equals(line))                    break;            }            ds.close();        } catch (Exception e) {            e.printStackTrace();        }    }}package cn.net;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;public class Rece implements Runnable{    private DatagramSocket ds = null;        public Rece(DatagramSocket ds) {        super();        this.ds = ds;    }    public void run(){        try {        while(true){            byte[] buf = new byte[1024];            DatagramPacket dp = new DatagramPacket(buf,buf.length);                ds.receive(dp);                int port = dp.getPort();                String ip = dp.getAddress().getHostName();                String text = new String(dp.getData(),0,dp.getLength());                System.out.println("ip:"+ip+" port:"+port+" text:"+text);                if("88".equals(text)){                    System.out.println("退出聊天!!");                }                //ds.close();            }                }catch (IOException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    }package cn.net;import java.net.DatagramSocket;import java.net.SocketException;public class Chat {    public static void main(String[] args) throws SocketException {        DatagramSocket rece = new DatagramSocket(9999);        DatagramSocket send = new DatagramSocket();        Send s = new Send(send);        Rece r = new Rece(rece);        Thread t1 = new Thread(s);        Thread t2 = new Thread(r);        t1.start();        t2.start();    }}

创建一个UDP的客户端,用来接受数据

发送端: 1,创建UDP的socket流,datagramsocket

          2,创建键盘输入流,system.in

          3,将需要的信息通过datagrampacket进行封装,封装的内容包括数据包的大小byte数组,长度,IP地址,发送信息的时候,必须要明确端口号

          4,通过UDP的socket流来发送数据包

          5,关闭UDP的socket流

接收端:1,创建UDP的socket流,datagramsocket

         2,创建一个byte数组,用UDP的socket流来接受数据包

         3,通过接受到的数据包,获取数据包的中内容,包括里面的内容,IP地址,端口号等

注意点:在发送端方面,对数据包进行实例化的时候,需要在其构造方法中明确,数据的内容(byte数组),数据的长度,要发送的目标地址,发送的端口,这个端口号是在datagrampacket,封装数据包的构造函数的时候明确的.

在接收端方面,创建数据包的接受对象,和UDP的socket流对象(在这个流对象中要明确我们在发送信息的时候,需要在哪个端口监听,与发送端的端口号要一致)

3,URL和URLConnection

URL是统一资源定位符,可以使用此类找到互联网上的资源(比如一个简单的网页)

URLConnection是封装访问远程网络资源一般方法的类,通过它可以建立与远程服务器的连接,检查远程资源的一些属性

package cn.wjd.ie_server;import java.io.IOException;import java.io.InputStream;import java.net.MalformedURLException;import java.net.URL;import java.net.URLConnection;public class URLDemo {    public static void main(String[] args) throws IOException {        String url_str = "http://127.0.0.1:8080/myweb/reg.html";        URL url = new URL(url_str);        //InputStream in = url.openStream();        //获取URL对象的url连接器对象,将连接封装成对象:java中内置可以解析具体协议的的对象+socket        URLConnection conn = url.openConnection();        System.out.println(conn.toString());        //sun.net.www.protocol.http.HttpURLConnection:http://127.0.0.1:8080/myweb/reg.html        byte[] buf = new byte[2588];    //    int len = in.read(buf);    //    String test = new String(buf,0,len);    //    System.out.println(test);    }}

4,TCP程序设计

在Java中,使用Socket来完成TCP程序的开发,使用此类可以方便的建立可靠的,双向的,持续的,点对点的通信连接.

在客户端当面,我们可以直接创建Socket对象,在服务端,先创建ServerSocket对象,通过该对象的accept方法,来获取到Socket,也就是说在整个TCP的信息的流通中,都是通过这个socket流来完成的.

ServerSocket类与Socket类

ServerSocket类是主要用于服务端程序的开发,用于接受客户端的连接请求,在服务器端每次运行时都是使用accept()方法等待客户端连接,此方法执行后,服务器端将进入阻塞状态,直到客户端连接之后程序才可以向下执行,此方法的返回值是Socket,每一个Socket都便是一个客户端对象.

大白话理解的话,在TCP客户端和服务端进行数据通讯的时候,存在的是一个Socket流,这个流首先是由客户端通过outputstream的形式发出的流通的管道中,然后到了服务端这边,我们得先ServerSocket对象,然后通过该实例化对象,来拿到管道中的Socket流,然后在通过inputstream来获取到这个管道中的信息.

但是在最后运行的时候,由于accept这个方法是阻塞的,我们得先运行服务端,再运行客户端这样才能顺利的进行通讯.

编写TCP客户端的步骤

1,创建Socket对象,同时指定要连接服务器的主机名称和连接端口号

2,创建Socket输出流,将需要发送的数据变成字节的形式(在Socket流中走的数据都是以字节的形式存在的),放在socket流中,在客户端中,发送信息,客户端->服务器端(out)     在服务器端反馈信息   服务器端->客户端(in)

3,关闭socket流

package cn.tcp;import java.io.IOException;import java.io.OutputStream;import java.net.InetAddress;import java.net.Socket;import java.net.UnknownHostException;public class Client {    public static void main(String[] args) throws UnknownHostException, IOException {        Socket s = new Socket(InetAddress.getByName("wjd"),8767);        OutputStream out = s.getOutputStream();        out.write("我是来发送数据的!!".getBytes());        s.close();    }}

编写TCP服务端的步骤

1,创建ServerSocket对象,在该对象的构造方法中,必须要明确客户端那边的端口号

2,使用accept()方法,来获取Socket流.

3,由于客户端那边已经out信息给服务端了,那么我们在服务端就要in信息出来,  搞了inoutstream对象,这样在TCP通信中就形成了一个完整的Socket流,有输出有输入

4,对in进行读取操作,读出客户端发给服务端的信息,然后将字节变成String,进行输出

5,关闭s流和ss流

package cn.tcp;import java.io.IOException;import java.io.InputStream;import java.net.ServerSocket;import java.net.Socket;public class Server {    public static void main(String[] args) throws IOException {        ServerSocket ss = new ServerSocket(8767);        Socket s = ss.accept();        InputStream in = s.getInputStream();        String ip = s.getInetAddress().getHostAddress();        int len = 0;        byte[] buf = new byte[1024];        len = in.read(buf);        String str = new String(buf,0,len);        System.out.println("接受客户端的内容:"+str+" ip:"+ip);        ss.close();        s.close();    }}

 

客户端和服务端进行数据交互,当在客户端输入小写字母的时候,在服务端进行处理,变成大写字母,反馈给客户端进行输出

客户端:  客户端->服务端发送信息 源键盘  目的socket的输出流(使用printWriter)

          服务端->客户端反馈信息  socket输入流,来接受服务端处理好的信息,并将处理好的信息打印到控制台上去

服务端:  接受客户端的信息  socket输入流,     服务端->客户端返回处理好的信息  printWriter流

readLine()是根据判断是否有换行来结束,所以在printwriter进行输出的时候,一定是println,这样才会有换行的标记

printwriter进行输出的时候,一定要进行刷新的动作,如果不刷新的话,数据只会进入printwriter流中,而不会进入socket流

package cn.tcp;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;public class TransServer {    public static void main(String[] args) throws IOException {        //获取socket流        ServerSocket ss = new ServerSocket(10000);        Socket s = ss.accept();        System.out.println(s.getInetAddress().getHostAddress());        //获取socket输出流  客户端->服务端的信息        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));                //获取socket输出流  服务端->客户端 信息的反馈        PrintWriter out = new PrintWriter(s.getOutputStream(),true);        //进行读写操作        String line;        while((line=bufIn.readLine())!=null){            System.out.println(line);            //将字母小写变成大写            String strUpper = line.toUpperCase();            //通过Socket流,服务端->客户端信息的反馈,将大写字母给到客户端去显示            out.println(strUpper);        }    }}
package cn.tcp;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.InetAddress;import java.net.Socket;import java.net.UnknownHostException;public class TransClient {    public static void main(String[] args) throws UnknownHostException, IOException {        //创建Socket流        Socket s = new Socket(InetAddress.getByName("wjd"),10000);        //创建源 键盘输入        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;        while((line=bufr.readLine())!=null){            if("over".equals(line))                break;            out.println(line);            //读取服务端返回的信息,该信息已经在服务端,把小写字母变成大写字母了.            String strUpper = bufIn.readLine();            System.out.println(strUpper);        }        s.close();//在socket流中植入了结束的标记    }}

TCP从客户端上上传图片或者文本文件到服务器

在Java IO中,到需要操作到文本文件的时候,源和目的的明确,使用到的是fileinputstream和fileoutputstream

操作图片.歌曲这些字节的时候,源和目的的明确,使用到的是filewriter和filereader

由于客户端和服务端之间有数据的交互,所以以后碰到该类问题的时候,我们在服务端完成数据传输动作的时候,必须要告诉服务端,这个时候客户端已经把事情办完了,不告诉服务端的话,服务端会一直处于等待状态,服务端的程序就不会结束,这个时候就得用到socket流中的一个方法1

服务器在操作文本数据,写入数据的时候,由于这边使用到了缓冲区,那么在写完数据的时候,必须要做一次刷新缓冲区的这个动作.

以后操作文本文件,这类的字符文件的时候,需要输出的话,可以优先考虑到IO中的打印流,打印流是输出信息最方便的类.

package cn.tcp;import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.InetAddress;import java.net.Socket;import java.net.UnknownHostException;public class UploadTXTClient {    public static void main(String[] args) throws UnknownHostException, IOException {        //创建socket流,明确地址和端口号        Socket s = new Socket(InetAddress.getByName("wjd"),10002);        //明确上传文件的源文件的地址        BufferedReader bufr = new BufferedReader(new FileReader("各种需求.txt"));        //创建socket输出流 客户端->服务端        PrintWriter out = new PrintWriter(s.getOutputStream(),true);        String lin = null;        //读取上传文件的(源文件)的信息,然后再通过打印流,就数据进入到socket流中去        while((lin=bufr.readLine())!=null){            out.println(lin);            }        //告诉服务器端,客户端这边的TXT文件的数据已经读完了        s.shutdownOutput();        //拿到服务端到客户端反馈的信息        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));        String str = bufIn.readLine();        System.out.println(str);        bufr.close();        s.close();    }}
package cn.tcp;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;public class UploadTXTServer {    public static void main(String[] args) throws IOException {        //得到socket流        ServerSocket ss = new ServerSocket(10002);        Socket s = ss.accept();        System.out.println(s.getLocalAddress().getHostAddress()+"connection...");        //确定需要上传后的文件的名称和目的        BufferedWriter bufw = new BufferedWriter(new FileWriter("load.txt"));        //得到socket中的输入流        BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));        String lin = null;        //拿到socket流中的数据,进行读取,并写入指定的文件        while((lin=bufIn.readLine())!=null){            bufw.write(lin);            bufw.newLine();            //由于使用了缓冲区,这边必要要刷新,才能将数据写入到目的文件中去            bufw.flush();        }                PrintWriter out = new PrintWriter(s.getOutputStream(),true);        out.println("OK!!");        ss.close();        s.close();    }}
package cn.tcp;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.InetAddress;import java.net.Socket;import java.net.UnknownHostException;public class LoadMP3Clinet {    public static void main(String[] args) throws UnknownHostException, IOException {        Socket s = new Socket(InetAddress.getByName("wjd"),10003);        FileInputStream fis = new FileInputStream("1.mp3");        OutputStream out = s.getOutputStream();        byte[] buf = new byte[1024];        int len = 0;        while((len=fis.read(buf))!=-1){            out.write(buf, 0, len);        }        s.shutdownOutput();        InputStream in = s.getInputStream();        byte[] serverBuf = new byte[1024];        int serverLen = 0;        while((serverLen=in.read(serverBuf))!=-1){            String str = new String(serverBuf,0,serverLen);            System.out.println(str);        }    }}
package cn.tcp;import java.io.FileOutputStream;import java.io.FileWriter;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;public class LoadMP3Server {    public static void main(String[] args) throws IOException {        ServerSocket ss = new ServerSocket(10003);        Socket s = ss.accept();        System.out.println(s.getInetAddress().getHostName()+"以连接上....");        FileOutputStream fos = new FileOutputStream("server.mp3");        InputStream in = s.getInputStream();        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());        ss.close();        s.close();    }}