1、Java支持基于流的通信和基于包的通信

基于流的通信使用TCP协议(传输控制协议)进行数据传输,传输是无损可靠的

基于包的通信使用UDP协议(用户数据报协议)进行数据传输,不能保证传输没有丢失

2、服务端和客户端套接字–基于流的通信

  • 客户端代码
package com.wangluo;

import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {

    public static void main(String[] args) {
        try {
            //1.创建客户端Socket,指定服务器端地址和端口
            Socket socket = new Socket("localhost",8888);
            //2.获取输出流,向服务器端发送信息
            OutputStream os = socket.getOutputStream();//字节输出流
            PrintWriter pw = new PrintWriter(os);//将输出流包装为打印流
            pw.write("用户名:admin;密码:123");
            pw.write("用户名:admin2;密码:456");
            pw.flush();
            socket.shutdownOutput();//关闭输出流,对于 TCP 套接字,任何以前写入的数据都将被发送
            //3.获取输入流,并读取服务器的响应信息
            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String info = null;
            while((info = br.readLine()) != null) {
                System.out.println("我是客户端,服务器端说:"+info);
            }
            //4.关闭资源
            br.close();
            is.close();
            pw.close();
            os.close();
            socket.close();

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

如果服务端的端口服务没有起来,运行客户端的程序会抛异常

java.net.ConnectException: Connection refused: connect
  • 服务端代码–服务多个客户
package com.wangluo;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

    public static void main(String[] args) {

        try {
            //1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口
            ServerSocket serverSocket = new ServerSocket(8888);
            //2.调用accept()方法开始监听,等待客户端 的连接
            System.out.println("***服务器即将启动,等待客户端的连接***");
            while (true) {
                //监听端口
                Socket socket = serverSocket.accept();
                new MyThread(socket).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static class MyThread extends Thread{
        private Socket socket;
        public MyThread(Socket socket){
            this.socket=socket;
        }
        @Override
        public void run() {
            try {
                server(socket);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        private void server(Socket socket) throws IOException {
            //3.获取输入流,并读取客户端信息
            InputStream is = socket.getInputStream();//字节输入流
            InputStreamReader isr = new InputStreamReader(is);//将字节输入流转换为字符流
            BufferedReader br = new BufferedReader(isr);//为输入流添加缓冲
            String info = null;
            while((info=br.readLine())!=null) {//循环读取客户端的信息
                System.out.println("我是服务器,客户端说:"+info);
            }
            OutputStream os = socket.getOutputStream();//字节输出流
            PrintWriter pw = new PrintWriter(os);//将输出流包装为打印流
            pw.write("我是服务端");
            pw.flush();
            socket.shutdownInput();//关闭输入流
             //4.关闭资源
            br.close();
            isr.close();
            is.close();
            socket.close();
        }
    }
}

如果服务端监听的端口已经被使用了,在启动服务端的服务时候会抛异常

java.net.BindException
  • 输出结果:(先启动服务端,再启动客户端)

服务端输出:我是服务器,客户端说:用户名:admin;密码:123用户名:admin2;密码:456

客户端输出:我是客户端,服务器端说:我是服务端

3、套接字发送和接受对象

  • 对象必须实现Serializable接口
package com.wangluo;

import java.io.Serializable;

public class Test implements Serializable{

    private static long serialVersionUID=1L;
    private int num;
    private String name;

    public Test(int num, String name){
        this.num=num;
        this.name=name;
    }
    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Test{" +
                "num=" + num +
                ", name='" + name + '\'' +
                '}';
    }
}
  • 客户端代码
package com.wangluo;

import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {

    public static void main(String[] args) {
        try {
            //1.创建客户端Socket,指定服务器端地址和端口
            Socket socket = new Socket("localhost",8888);
            //2.获取输出流,向服务器端发送信息
            OutputStream os = socket.getOutputStream();//字节输出流
//            PrintWriter pw = new PrintWriter(os);//将输出流包装为打印流
//            pw.write("用户名:admin;密码:123");
//            pw.write("用户名:admin2;密码:456");
//            pw.flush();
            ObjectOutputStream objectOutputStream=new ObjectOutputStream(os);
            objectOutputStream.writeObject(new Test(123,"deng"));
            objectOutputStream.flush();
            socket.shutdownOutput();//关闭输出流
            //3.获取输入流,并读取服务器的响应信息
            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String info = null;
            while((info = br.readLine()) != null) {
                System.out.println("我是客户端,服务器端说:"+info);
            }
            //4.关闭资源
            br.close();
            is.close();
//            pw.close();
            objectOutputStream.close();
            os.close();
            socket.close();

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 服务端代码
package com.wangluo;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

    public static void main(String[] args) {

        try {
            //1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口
            ServerSocket serverSocket = new ServerSocket(8888);
            //2.调用accept()方法开始监听,等待客户端 的连接
            System.out.println("***服务器即将启动,等待客户端的连接***");
            while (true) {
                //监听端口
                Socket socket = serverSocket.accept();
                new MyThread(socket).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static class MyThread extends Thread{
        private Socket socket;
        public MyThread(Socket socket){
            this.socket=socket;
        }
        @Override
        public void run() {
            try {
                server(socket);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        private void server(Socket socket) throws Exception {
            //3.获取输入流,并读取客户端信息
            InputStream is = socket.getInputStream();//字节输入流
//            InputStreamReader isr = new InputStreamReader(is);//将字节输入流转换为字符流
//            BufferedReader br = new BufferedReader(isr);//为输入流添加缓冲
//            String info = null;
//            while((info=br.readLine())!=null) {//循环读取客户端的信息
//                System.out.println("我是服务器,客户端说:"+info);
//            }

            ObjectInputStream objectInputStream=new ObjectInputStream(is);
            Object test=objectInputStream.readObject();
            System.out.println("我是服务器,客户端说:"+test);
            OutputStream os = socket.getOutputStream();//字节输出流
            PrintWriter pw = new PrintWriter(os);//将输出流包装为打印流
            pw.write("服务端应答");
            pw.flush();
            socket.shutdownInput();//关闭输入流
             //4.关闭资源
//            br.close();
//            isr.close();
            objectInputStream.close();
            is.close();
            socket.close();
        }
    }
}
  • 输出结果:

服务端:我是服务器,客户端说:Test{num=123, name=’deng’}

客户端:我是客户端,服务器端说:服务端应答

版权声明:本文为shixiemayi原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/shixiemayi/p/9478582.html