Java Socket应用

网络基础

  1. 端口号范围0-65535,系统保留0-1023,常见端口http:80,ftp:21,telnet:23
  2. socket=ip+端口
  3. java主要分为InetAdress,URL,Socket(TCP),DatagramSocket(UDP)等类

InetAddress类

InetAddress类没有构造方法,可以通过静态方法获取InetAddress实例对象。

  1. 获取本地主机:getLocalHost()
  2. 通过主机名获取实例:getByName(String Host)
  3. 对实例操作:getHostName()获取主机名,getHostAddress()获取主机ip地址,getAddress()以字节数组的形式返回ip地址

测试:

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;

public class Test{
    public static void main(String[] args) throws UnknownHostException{
        //获取本机名
        InetAddress address=InetAddress.getLocalHost();
        System.out.println(address.getHostName());//输出主机名
        System.out.println(address.getHostAddress());//输出主机ip地址
        byte[] bytes=address.getAddress(); //用字节数组表示ip地址
        System.out.println(Arrays.toString(bytes));
        //通过主机名获取
        InetAddress address2=InetAddress.getByName("你们的大神");//通过名字获取,name可为主机名或者ip地址
        //InetAddress address2=InetAddress.getByName("baidu.com");
        //InetAddress address2=InetAddress.getByName("192.168.0.109");
        System.out.println(address2.getHostName());
        System.out.println(address2.getHostAddress());
        byte[] bytes2=address2.getAddress();
        System.out.println(Arrays.toString(bytes2));
    }
}

URL类

常用构造方法:
  1. URL(String spec)
  2. URL(String protocol, String host, int port,String file)
  3. URL(URL context, String spec) 通过已存在的URL构建
常用get方法:

getRef()获取锚点,getQuery()获取查询字符串,getPort()获取端口号(未指定默认为-1,而浏览器默认为80),其他的见测试用例。

测试:

import java.net.MalformedURLException;
import java.net.URL;

public class Test {
    public static void main(String[] args) throws MalformedURLException {
        URL imooc = new URL("http://www.imooc.com"); // 直接创建
        URL url = new URL(imooc, "/index.html?username=tom#test");// 根据已存在的创建,?表示参数,#表示锚点
        System.out.println(url.getProtocol());
        System.out.println(url.getHost());
        System.out.println(url.getPort()); //如未指定,则返回-1;
        System.out.println(url.getPath());
        System.out.println(url.getFile());
        System.out.println(url.getRef()); //锚点
        System.out.println(url.getQuery()); //查询字符串
    }
}

结果:
http
www.imooc.com
-1
/index.html
/index.html?username=tom
test
username=tom
获取页面内容

使用openStream()获取字节输入流。
测试:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;

//通过URL获取页面内容
public class Test {
    public static void main(String[] args) throws IOException {
        URL url=new URL("http://www.baidu.com");
        InputStream is=url.openStream();//使用openStream获取字节输入流
        InputStreamReader isr=new InputStreamReader(is,"utf-8");//在字节到字符流时需要指定编码方式,避免乱码
        BufferedReader br=new BufferedReader(isr); //添加缓冲流
        
        String data=br.readLine();
        while (data!=null){
            System.out.println(data);
            data=br.readLine();
        }
    }
}

Socket TCP通信

流程

创建ServerSocket和Socket,打开输入输出流,进行操作读写操作,关闭输入输出流,关闭socket。

具体
  1. ServerServer类是服务端socket,侦听客户端的请求。
    常用构造:ServerSocket(int port)
    常用实例方法:accept(),close(),getInetAddress(),getPort()
  2. Socket类是通信的端点。
    常用构造:Socket(InetAddress address,int port)或Socket(String host,int port)
    常用实例方法:getInetAddress(),close()
    getInputStream(),getOutputStream(),shutdownInput(),shutdownOutput()
  3. 多线程服务器,可以接受多个客户端的请求,创建一个线程类,完成对客户端的操作。
测试

Server.java (服务器)

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

    public static void main(String[] args) throws IOException {
        // 1.创建服务器ServerSocket,绑定端口
        ServerSocket serverSocket = new ServerSocket(8888);
        // 2.使用accept侦听,侦听来自客户端的连接
        System.out.println("****服务器正在启动,侦听连接****");
        int count=0;
        Socket socket;
        while (true) {
            socket = serverSocket.accept();
            ServerThread serverThread = new ServerThread(socket);
            serverThread.start();
            count++;
            System.out.println("client number:"+count);
            InetAddress address=socket.getInetAddress();
            System.out.println("client address:"+address.getHostAddress());
        }
        // serverSocket.close();不会执行到这一步,一直循环,去掉该语句。    
    }
}

ServerThread.java (服务器线程)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;

public class ServerThread extends Thread {
    Socket socket = null;

    public ServerThread(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        InputStream is = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        OutputStream os = null;
        PrintWriter pw = null;
        try {
            is = socket.getInputStream();
            isr = new InputStreamReader(is);
            br = new BufferedReader(isr); // 添加缓冲流
            String data = null;
            while ((data = br.readLine()) != null) {
                System.out.println("我是服务端,客户端说:" + data);
            }
            socket.shutdownInput(); // 关闭socket的输入流
            os = socket.getOutputStream();
            pw = new PrintWriter(os);
            pw.write("hello");
            pw.flush();
            socket.shutdownOutput();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (pw != null)
                    pw.close();
                if (os != null)
                    os.close();
                if (br != null)
                    br.close();
                if (isr != null)
                    isr.close();
                if (is != null)
                    is.close();
                if (socket != null)
                    socket.close();
            } catch (IOException e2) {
                // TODO: handle exception
                e2.printStackTrace();
            }

        }

    }
}

Client.java (客户端)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {
    public static void main(String[] args) throws UnknownHostException, IOException {
        //1.创建客户端socket,指定服务器地址和端口
        Socket socket=new Socket("localhost", 8888);//本地服务器的8888端口
        //2. 获取输出流,发送信息
        OutputStream os=socket.getOutputStream();
        PrintWriter pw=new PrintWriter(os);
        pw.write("admin:456");
        pw.flush();
        socket.shutdownOutput();
        // 3. 获取输入流,接收信息
        InputStream is=socket.getInputStream();
        InputStreamReader isr=new InputStreamReader(is);
        BufferedReader br=new BufferedReader(isr); //添加缓冲流
        String  data=null;
        while((data=br.readLine())!=null){
            System.out.println("我是客户端,服务端说:"+data);
        }
        socket.shutdownInput(); //关闭socket的输入流  
        //3.关闭资源
        is.close();
        isr.close();
        br.close();
        pw.close();
        os.close();
        socket.close();
    }
}

Socket UDP通信

流程

客户端和服务器创建DatagramPacket保存相应数据,创建DatagramSocket,使用DatagramSocket实例的send(),receive()方法来进行通信

具体
  1. DatagramPacket类是UDP用来发送的数据报,UDP无连接,所以数据中可以包含ip地址,端口号等。另外,需要另外定义一个byte[]类型的数组,用来存放数据,这个数组与DatagramPacket实例实质上是同一个。
  2. DatagramSocket类是用来发送或者接受数据报的,主要使用该实例的receive(DatagramPacket packet)和send(DatagramPacket packet)方法,分别把数据存放在packet中的数组中(自己另外定义的),以及相关信息。
  3. 也可以用多线程服务器。
测试

UDPserver.java(UDP服务器)

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UDPServer {

    public static void main(String[] args) throws IOException {
        // 1. 创建服务器端datagramsocket,指定端口
        DatagramSocket socket = new DatagramSocket(8800);
        // 2. 创建数据报,用于接受客户端发送的数据
        byte[] data = new byte[1024];
        DatagramPacket packet = new DatagramPacket(data, 0, data.length);
        // 3.接受客户端发送的数据,存放在packet
        System.out.println("***服务器正在启动***");
        socket.receive(packet);
        // 4.读取数据
        String info = new String(data, 0, packet.getLength());
        System.out.println("i'm server,client say:" + info);

        // 数据,发送至客户端
        // 1.得到客户端地址,端口,数据
        InetAddress address = packet.getAddress();
        int port = packet.getPort();
        byte[] data2 = "hello".getBytes();
        // 2.创建数据报
        DatagramPacket packet2 = new DatagramPacket(data2, data2.length, address, port);
        // 3.响应客户端
        socket.send(packet2);
        // 4.关闭资源
        socket.close();
    }
}

UDPclient(客户端)

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UDPClient {
    public static void main(String[] args) throws IOException {
        // 1.定义服务器的地址,端口,数据
        InetAddress address = InetAddress.getByName("localhost");
        int port = 8800;
        byte[] data = "admin:123".getBytes();
        // 2.创建数据报,包含信息
        DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
        // 3.创建DatagramSocket对象
        DatagramSocket socket = new DatagramSocket();
        socket.send(packet);

        // 接受来自服务器数据
        byte[] data2 = new byte[1024];
        DatagramPacket packet2 = new DatagramPacket(data2, 0, data2.length);
        // 3.接受客户端发送的数据,存放在packet
        socket.receive(packet2);
        // 4.读取数据
        String info = new String(data2, 0, packet2.getLength());
        System.out.println("i'm client,server say:" + info);
    }
}

你可能感兴趣的:(Java Socket应用)