黑马程序员_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

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

黑马程序员_Java网络编程

我们去获取本家的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流中的一个方法黑马程序员_Java网络编程

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

以后操作文本文件,这类的字符文件的时候,需要输出的话,可以优先考虑到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();
    }

}

黑马程序员_Java网络编程,布布扣,bubuko.com

黑马程序员_Java网络编程

上一篇:Java模式(适配器模式)


下一篇:使用c3p0与DBCP连接池,造成的MySql 8小时问题解决方案