网络编程二

151 阅读2分钟

网络编程Socket

DatagramSocket——创建一个UDP版本的socket对象

  • receive: 接收数据
  • send: 发送数据
  • close: 释放资源

DatagramPacket——表示一个UDP数据报

使用

服务器

public class UdpEchoServer {
    //多个进程不能绑定一个端口
    //一个进程可以绑定多个端口
    private DatagramSocket socket = null;
    public UdpEchoServer(int port) throws SocketException {
        socket = new DatagramSocket(port);   //port:端口号
    }
    public void start() throws IOException {
        System.out.println("启动服务器");
        while(true){
            DatagramPacket packet = new DatagramPacket(new byte[1024] , 1024);   //用于接受
            socket.receive(packet);
            String request = new String(packet.getData() ,0, packet.getLength(),"UTF-8");
            String response = process(request);
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes() ,
                    response.getBytes().length,
                    packet.getSocketAddress());    //用于发送
            socket.send(responsePacket);
            System.out.printf("[%s:%d] req: %s,resp:%s\n" , packet.getAddress().toString() , packet.getPort()
            ,request , response);
        }
    }
    public String process(String request){
        return request;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer server = new UdpEchoServer(9090);
        server.start();
    }
}

客户端

public class UdpEchoClient {
   //通常服务器弄端口号的时候是自己定的,客户端的端口号是随机的
    private DatagramSocket socket = null;
    private String serverIp;
    private int port;
    public UdpEchoClient(String serverIp , int port) throws SocketException {
        socket = new DatagramSocket();
        this.serverIp = serverIp;
        this.port = port;
    }
    public void start() throws IOException {
        Scanner sc = new Scanner(System.in);
        while(true){
            String request = sc.next();
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes() , request.getBytes().length ,
                    InetAddress.getByName(serverIp) , port);  //用于发送
            socket.send(requestPacket);
            DatagramPacket responsePacket = new DatagramPacket(new byte[1024] , 1024);
            socket.receive(responsePacket);
            String response = new String(responsePacket.getData() , 0 , responsePacket.getLength() , "UTF-8");
            System.out.printf("req: %s , resp: %s/n" , request , response);
        }
    }

    public static void main(String[] args) throws IOException {
        UdpEchoClient client = new UdpEchoClient("127.0.0.1" , 9090);
        client.start();
    }
}

记住,要先开启服务器,后面开启客户端。

ServerSocket——用于TCP

Socket——用于TCP

先要建立连接才可以用。

使用

服务器

public class TcpEchoServer {
    private ServerSocket serverSocket = null;
    public TcpEchoServer(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }
    public void start() throws IOException {
        System.out.println("服务器开始");
        while(true){
            Socket clientSocket = serverSocket.accept();   //接听,如果没有客户端来就会阻塞
            Thread t = new Thread(()->{                       //这个是为了服务器可以接收多个客户端。
                processConnection(clientSocket);
            });
            t.start();
        }
    }
    public void processConnection(Socket clientSocket){
        System.out.printf("[%s:%d]" , clientSocket.getInetAddress().toString() , clientSocket.getPort());
        try(InputStream inputStream = clientSocket.getInputStream()){
            try(OutputStream outputStream = clientSocket.getOutputStream()){
                Scanner sc = new Scanner(inputStream);
                while(true){
                    //读取请求
                    if(!sc.hasNext()){
                        System.out.printf("[%s:%d]客户端断开连接!" , clientSocket.getInetAddress().toString() , clientSocket.getPort());
                        break;
                    }
                    //根据请求返回响应
                    String request = sc.next();
                    String response = process(request);
                    PrintWriter printWriter = new PrintWriter(outputStream);
                    printWriter.println(response);
                    printWriter.flush();   //刷新缓冲区,让客户端能第一时间看到响应
                    System.out.printf("[%s:%d] req:%s resp:%s\n" , clientSocket.getInetAddress().toString() , clientSocket.getPort()
                    ,request , response);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                clientSocket.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
    public String process(String request){
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer server = new TcpEchoServer(9090);
        server.start();
    }
}

客户端

public class TcpEchoClient {
    private Socket socket = null;
    public TcpEchoClient() throws IOException {
        socket = new Socket("127.0.0.1" , 9090);   //这边连接的是服务器的IP和端口
    }
    public void start(){
        System.out.println("和服务器连接成功");
        Scanner sc = new Scanner(System.in);
        try(InputStream inputStream = socket.getInputStream()) {
            try(OutputStream outputStream = socket.getOutputStream()){
                while(true){
                    String request = sc.next();
                    PrintWriter printWriter = new PrintWriter(outputStream);
                    printWriter.println(request);
                    printWriter.flush();
                    Scanner scInput = new Scanner(inputStream);
                    String response = scInput.next();
                    System.out.printf("req:%s resp:%s\n" , request , response);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) throws IOException {
        TcpEchoClient client = new TcpEchoClient();
        client.start();
    }
}

优化,加上线程池

public void start() throws IOException {
        System.out.println("服务器开始");
        ExecutorService pool = Executors.newCachedThreadPool();
        while(true){
            Socket clientSocket = serverSocket.accept();   //接听,如果没有客户端来就会阻塞
//            Thread t = new Thread(()->{                       //这个是为了服务器可以接收多个客户端。
//                processConnection(clientSocket);
//            });
//            t.start();
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    processConnection(clientSocket);
                }
            });
        }
    }

这样提高了效率。