Java网络编程

来源:互联网 发布:b站直播间刷人气源码 编辑:程序博客网 时间:2024/06/05 23:49

一、InetAddress

 

InetAddress类来代表IP地址,2个子类:Inet4Address, Inet6Address,它们分别代表IPv4地址和IPv6地址。

InetAddress类没有构造器,而是提供了两个静态方法来获取InetAddress实例:

1、getByName(String host):根据主机获取对应的InetAddress对象。

2、getByAddress(byte口addr):根据原始IP地址来获取。


InetAddress还提供了如下三个方法来获取InetAddress实例对应的IP地址和主机名:

1)String getCanonicalHostName():获取此IP地址的全限定域名。

2)String getHostAddress():返回该InetAddress实例对应的IP地址字符串(以字符串形式)。

3)String getHostName():获取此IP地址的主机名。


除此之外,InetAddress类还提供了一个getLocalHost()方法来获取本机IP地址对应的InetAddress实例。isReachable()方法,用于测试是否可以到达该地址。   


public class Test01{    public static void main(String[] args) throws UnknownHostException{        System.out.println("--------根据本地主机获取InetAddress实例-----------");        //获取本机的InetAddress实例        InetAddress address1 = InetAddress.getLocalHost();         //直接输出InetAddress对象        System.out.println(address1);         //输出结果        System.out.println("计算机名称:"+address1.getHostName());        System.out.println("IP地址:"+address1.getHostAddress());         //获取字节数组形式的IP地址        byte[] bytes = address1.getAddress();        System.out.println("字节数组形式的IP地址:"+Arrays.toString(bytes));         System.out.println("--------根据主机名获取InetAddress实例-----------");        //根据主机名获取InetAddress实例        InetAddress address2 = InetAddress.getByName("HTACLW0UOMUIZKE");        //直接输出InetAddress对象        System.out.println(address2);         System.out.println("计算机名称:"+address2.getHostName());        System.out.println("IP地址:"+address2.getHostAddress());         System.out.println("--------根据IP地址获取InetAddress实例-----------");        //根据IP地址获取InetAddress实例        InetAddress address3 = InetAddress.getByName("192.168.0.109");        //直接输出InetAddress对象        System.out.println(address3);         System.out.println("计算机名称:"+address3.getHostName());        System.out.println("IP地址:"+address3.getHostAddress());    }}

 


二、ServerSocket、Socket

        TCP/IP是一种可靠的网络协议,它在通信的两端各建立一个Socket,形成网络虚拟链路。Java对基于TCP协议的网络通信提供了良好的封装,Java使用Socket对象来代表两端的通信端口,并通过Socket产生IO流进行网络通信。

使用ServerSocket创建TCP服务器端.

(1)

        Java中能接收其他连接请求的类是ServerSocket,ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一直处于等待状态。ServerSocket包含一个监听来自客户端请求的方法。

Socket accept()接到请求,返回与客户端Socket对应的Socket(每个TCP连接有两个Socket)否则该方法将一直处于等待状态,线程也被阻塞。


ServerSocket构造器

ServerSocket(int port):用指定的端口port来创建一个ServerSocket。该端口应该有一个有效的端口数值,即0~65535。

ServerSoccket(int port,int backlog)

ServerSocket(int port,int backlog,InetAddress localAddr)

 

(2)使用Socket进行通信

客户端使用Socket的构造器来连接到指定服务器,Socket构造器。

Socket(InetAddress/String remoteAddress,int port)创建连接到指定远程主机、端口的Socket,没指定本地地址、本地端口,默认使用本地主机的默认IP地址,默认使用系统动态分配的端口

Socket(InetAddress/String remoteAddress,int port,InetAddress localAddr,int localPort)指定本地IP地址和本地端口,适用于本地主机有多个IP地址的情形





当客户端、服务器端产生了对应的Socket之后,程序无须再区分服务器端、客户端,而是通过各自的Socket进行通信。Socket提供了两个方法来获取输入流和输出流。

InputStream getInputStream()

返回该Socket对象对应的输入流

OutputStream getOutputStream()

返回该Socket对象对应的输出流出数据

 

三、例子

(1)TCP(单线程)

 

public class Server {    public static void main(String[] args) throws IOException{        //创建一个ServerSocket,用于监听客户端Socket的连接请求        ServerSocket ss = new ServerSocket(30000);        //采用循环换不断地接收来自客户端的请求        while (true){            //每当接收到客户端Socket的请求时,服务器端也对应产生一个Socket            Socket s = ss.accept();            //将Socket对应的输出流包装成PrintStream            PrintStream ps = new PrintStream(s.getOutputStream());            //进行普通的IO操作            ps.println("您好,您收到了服务器的问候!");            //关闭输出流,关闭Socket            ps.close();            s.close();        }    }} ****************************************public class Client {    public static void main(String[] args) throws IOException{           Socket socket = new Socket("127.0.0.1", 30000);        //将Socket对应的输入流包装成BufferedReader        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));        //进行普通IO操作        String line = br.readLine();        System.out.println("来自服务器的数据:" + line);        //关闭输入流,关闭Socket        br.close();        socket.close();    }}


(2)多线程

        命令行界面的C/S聊天室应用,服务器端应该包含多个线程,每个Socket对应一个线程,该线程负责读取Socket对应输入流的数据(从客户端发送过来的数据),并将读到的数据向每个Socket输出流发送一次(将一个客户端发送的数据“广播”给其他客户端),因此需要在服务器端使用List来保存Socket

首先是服务器端的实现代码,一共有两个类,一个是创建ServerSocket监听的主类,一个是负责处理每个Socket通信的线程类。 
监听主类:

public class MyServer {    //定义保存所有Socket的ArrayList,并将其包装为线层安全的    public static List<Socket> socketList = Collections.synchronizedList(new ArrayList<>());    public static void main(String[] args) throws IOException{        ServerSocket ss = new ServerSocket(30001);        while (true){            //此行代码会阻塞,将一直等待别人的连接            Socket s = ss.accept();            socketList.add(s);            //每当客户端连接后启动一个ServerThread线程为该客户端服务            new Thread(new ServerThread(s)).start();        }    }}

  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

          服务器端只负责接收客户端Socket的连接请求,每当客户端Socket连接到该ServerSocket之后,程序将对应Socket加入socketList集合中保存,并为该Socket启动一个线程,该线程负责处理该Socket所有的通信任务。

负责处理Socket通信的线程类:

public class ServerThread implements Runnable{    //定义当前线程所处理的Socket    Socket s = null;    //该线程所处理的Socket对应的输入流    BufferedReader br = null;    public ServerThread(Socket s) throws IOException{        this.s = s;        //初始化该Socket对应的输入流        br = new BufferedReader(new InputStreamReader(s.getInputStream()));    }    public void run(){        try{            String content = null;            //采用循环不断地从Socket中读取客户端发送过来的数据            while ((content = readFromClient()) != null){                //遍历socketList中的每个socket                //将读到的内容向每个Socket发送一次                for(Socket s : MyServer.socketList){                    PrintStream ps = new PrintStream(s.getOutputStream());                    ps.println(content);                }            }        }catch (IOException e){            e.printStackTrace();        }    }    //定义读取客户端数据的方法    private String readFromClient(){        try{                return br.readLine();        }        //如果捕获异常,则表明该Socket对应的客户端已经关闭        catch (IOException e){            //删除该Socket            MyServer.socketList.remove(s);        }        return null;    }}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

          每个客户端包含两个线程一个负责读取用户的键盘输入,并将用户输入的数据写入Socket对应的输出流中;一个负责读取Socket对应输入流中的数据(从服务端发送过来的数据),并将这些数据打印输出。其中负责读取用户键盘输入的线程由MyClient负责,也就是有程序的线程负责。

客户端主程序:

public class MyClient {    public static void main(String[] args) throws Exception{        Socket s = new Socket("127.0.0.1", 30001);        //客户端启动ClientThread线程不断地读取来自服务器的数据        new Thread(new ClientThread(s)).start();        //获取该Socket对应的输出流        PrintStream ps = new PrintStream(s.getOutputStream());        String line = null;        //不断地读取键盘输入        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));        while ((line = br.readLine()) != null){            //将用户的键盘输入内容写入Socket对应的输出流            ps.println(line);        }    }}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

客户端线程:

public class ClientThread implements Runnable{    //该线程负责处理的Socket    private Socket s;    //该线程所处理的Socket对应的输入流    BufferedReader br = null;    public ClientThread(Socket s) throws IOException{        this.s = s;        br = new BufferedReader(new InputStreamReader(s.getInputStream()));    }    public void run(){        try{            String content = null;            //不断地读取Socket输入流中的内容,并将这些内容打印输出            while ((content = br.readLine()) != null){                System.out.println(content);            }        }catch (Exception e){            e.printStackTrace();        }    }}


原创粉丝点击