socket系统化入门

时间:2019-09-13
本文章向大家介绍socket系统化入门,主要包括socket系统化入门使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

1.简单socket完成消息发送与接收

服务端:

package com.wfd360.com.socket;

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

/**
 * @Copyright (C) 
 * @Author: LI DONG PING
 * @Date: 2019-09-01 15:14
 * @Description:
 */
public class ServerSocketDemo {
    /**
     * ServerSocket 的构造方法如下所示。
     * ServerSocket():无参构造方法。
     * ServerSocket(int port):创建绑定到特定端口的服务器套接字。
     * ServerSocket(int port,int backlog):使用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口。
     * ServerSocket(int port,int backlog,InetAddress bindAddr):使用指定的端口、监听 backlog 和要绑定到本地的 IP 地址创建服务器。
     * <p>
     * ===================================================================================================================
     * ServerSocket 的常用方法如下所示。
     * Server accept():监听并接收到此套接字的连接。
     * void bind(SocketAddress endpoint):将 ServerSocket 绑定到指定地址(IP 地址和端口号)。
     * void close():关闭此套接字。
     * InetAddress getInetAddress():返回此服务器套接字的本地地址。
     * int getLocalPort():返回此套接字监听的端口。
     * SocketAddress getLocalSoclcetAddress():返回此套接字绑定的端口的地址,如果尚未绑定则返回 null。
     * int getReceiveBufferSize():获取此 ServerSocket 的 SO_RCVBUF 选项的值,该值是从 ServerSocket 接收的套接字的建议缓冲区大小。
     *
     * @param args 服务端设计步骤:
     *             1.创建socket服务端
     *             2.监听客户端
     *             3.获取输入流
     *             4.输出
     */
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        Socket server = null;
        BufferedReader reader = null;
        BufferedWriter writer = null;
        try {
            //1.建立socket服务器
            serverSocket = new ServerSocket(1001);
            System.out.println("服务端创建成功----");
            while (true) {
                //2.监听客户端连接
                server = serverSocket.accept();
                //3.读取客户端数据
                reader = new BufferedReader(new InputStreamReader(server.getInputStream()));
                String s = reader.readLine();
                System.out.println("服务端收到数据:" + s);
                //4.响应客户端
                writer = new BufferedWriter(new OutputStreamWriter(server.getOutputStream()));
                writer.write("已经收到数据[" + s + "]\n");
                //清除缓存
                writer.flush();
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                //关闭资源
                if (writer != null) {
                    writer.close();
                }
                if (reader != null) {
                    reader.close();
                }
                if (server != null) {
                    server.close();
                }
                if (serverSocket != null) {
                    serverSocket.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


}
View Code

客户端:

package com.wfd360.com.socket;

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

/**
 * @Copyright
 * @Author: LI DONG PING
 * @Date: 2019-09-01 15:50
 * @Description:
 */
public class ClientSocketDemo {
    /**
     * 客户端设计逻辑:
     * 1.创建socket通信,设置IP和端口
     * 2.建立IO输出流,向服务端发送数据
     * 3.建立IO输入流,读取服务端应答的数据
     *
     * @param args
     */
    public static void main(String[] args) {
        Socket socket = null;
        BufferedWriter writer = null;
        BufferedReader reader = null;


        try {
            //1.创建socket通信
            socket = new Socket("localhost", 1001);
            //2.建立IO输出流,向服务端发送数据
            writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            //注意这里必须加\n,因为是按照行读取
            writer.write("短信发送2\n");
            writer.flush();
            //3.建立IO输入流,读取服务端应答的数据
            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String s = reader.readLine();
            System.out.println("客户端收到数据:" + s);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
                if (writer != null) {
                    writer.close();
                }
                if (socket != null) {
                    socket.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
View Code

2.socket中的常用io操作

  常用类:https://www.cnblogs.com/newAndHui/p/11514269.html

  案例:

package com.wfd360.com.io;

import org.junit.Test;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @Copyright (C) 
 * @Author: LI DONG PING
 * @Date: 2019-09-12 11:15
 * @Description:
 */
public class FileDemo {
    /**
     * 需求:
     * 将a.txt 复制到 b.txt
     *
     * @param args
     */
    public static void main(String[] args) throws Exception {
    }

    @Test
    public void test2() throws Exception {
       // String filePath="E:\\test\\day18_数据结构.docx";
        String filePath="E:\\test\\a.txt";
        String filePathNew="E:\\test\\b.txt";
        //1.读取本地文件a
        File file = new File(filePath);
        DataInputStream dataInputStream = new DataInputStream(new FileInputStream(file));
        //读取文件名
       // String fileName = dataInputStream.readUTF();
        //读取文件大小
       // long fileSize = dataInputStream.readLong();
       // System.out.println("fileName="+fileName+",fileSize="+fileSize);
        //准备写入文件对象
        File fileNew = new File(filePathNew);
       // fileNew.createNewFile();
        DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream(fileNew));

        //按照字节读取文件
        byte[] aByte = new byte[128];
        System.out.println("length="+aByte.length);
        int read = dataInputStream.read(aByte, 0, aByte.length);
        while (read!=-1){
            //当前文件内容
            String s = new String(aByte,"gbk");
            System.out.println("read="+read+"s="+s);
            //写入文件
            dataOutputStream.write(aByte,0,read);
            dataOutputStream.flush();
            read = dataInputStream.read(aByte, 0, aByte.length);
        }

        //2.写入到本地文件b
    }

    /**
     * 需求:
     * 将a.txt 复制到 b.txt
     * 使用:FileInputStream,FileOutputStream
     *
     * @throws Exception
     */
    @Test
    public void test1() throws Exception {
        //1:读取a.txt中的内容
        //1.1.建立文件
        File file = new File("D:\\test\\a.txt");
        //1.2.读取文件内容 字节流
        FileInputStream fileInputStream = new FileInputStream(file);
        //1.3.转变为处理流 gb2312
        BufferedReader reader = new BufferedReader(new InputStreamReader(fileInputStream, "gbk"));
        //1.4.按照行读取数据
        List<String> content = new ArrayList<String>();
        String line = reader.readLine();
        while (line != null) {
            System.out.println("line=" + line);
            content.add(line);
            //读取下一行
            line = reader.readLine();
        }

        //2:写入到b.txt中
        //2.1.创建文件
        File fileB = new File("D:\\test\\b.txt");
        boolean newFile = fileB.createNewFile();
        System.out.println("newFile=" + newFile);
        //2.2.创建写入文件字节流
        FileOutputStream fileOutputStream = new FileOutputStream(fileB);
        //2.3.转变为处理流
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fileOutputStream, "gbk"));
        for (String s : content) {
            writer.write(s);
        }
        writer.flush();
        writer.close();
    }
}
View Code

3.socket中java对象传送

  java对象

package com.wfd360.com.socketJava.model;

import java.io.Serializable;

/**
 * @Copyright (C) 
 * @Author: LI DONG PING
 * @Date: 2019-09-12 17:48
 * @Description:
 */
public class User implements Serializable {
    private String name;
    private Integer age;

    public User() {
    }

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
View Code

  服务端:

package com.wfd360.com.socketJava;

import com.wfd360.com.socketJava.model.User;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @Copyright (C) 
 * @Author: LI DONG PING
 * @Date: 2019-09-01 15:14
 * @Description:
 */
public class ServerSocketDemo {
    /**
     * @param args 服务端设计步骤:
     *             1.创建socket服务端
     *             2.监听客户端
     *             3.获取输入流
     *             4.输出
     */
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        Socket server = null;
        ObjectInputStream objectInputStream = null;
        ObjectOutputStream objectOutputStream = null;
        try {
            //1.建立socket服务器
            serverSocket = new ServerSocket(1002);
            System.out.println("服务端创建成功----");
            while (true) {
                //2.监听客户端连接
                server = serverSocket.accept();
                //3.读取客户端数据
                objectInputStream = new ObjectInputStream(server.getInputStream());
                User user = (User) objectInputStream.readObject();
                System.out.println("服务端收到数据:" + user);
                //4.响应客户端
                objectOutputStream = new ObjectOutputStream(server.getOutputStream());
                user.setName("我来做服务端");
                objectOutputStream.writeObject(user);
                //清除缓存
                objectOutputStream.flush();
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                //关闭资源
                if (objectOutputStream != null) {
                    objectOutputStream.close();
                }
                if (objectInputStream != null) {
                    objectInputStream.close();
                }
                if (server != null) {
                    server.close();
                }
                if (serverSocket != null) {
                    serverSocket.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


}
View Code

  客户端:

package com.wfd360.com.socketJava;

import com.wfd360.com.socketJava.model.User;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

/**
 * @Copyright (C) 
 * @Author: LI DONG PING
 * @Date: 2019-09-01 15:50
 * @Description:
 */
public class ClientSocketDemo {
    /**
     * 客户端设计逻辑:
     * 1.创建socket通信,设置IP和端口
     * 2.建立IO输出流,向服务端发送数据
     * 3.建立IO输入流,读取服务端应答的数据
     *
     * @param args
     */
    public static void main(String[] args) {
        Socket socket = null;
        ObjectOutputStream writer = null;
        ObjectInputStream reader = null;


        try {
            //1.创建socket通信
            socket = new Socket("localhost", 1002);
            //2.建立IO输出流,向服务端发送数据
            writer = new ObjectOutputStream(socket.getOutputStream());
            writer.writeObject(new User("无忌", 19));
            writer.flush();
            //3.建立IO输入流,读取服务端应答的数据
            reader = new ObjectInputStream(socket.getInputStream());
            User o = (User) reader.readObject();
            System.out.println("==>" + o);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
                if (writer != null) {
                    writer.close();
                }
                if (socket != null) {
                    socket.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
View Code

4.多线程下的socket

  多线程处理类

package com.wfd360.com.socketThread.thread;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class HandleServerThread extends Thread {
    private Socket socket;

    public HandleServerThread(){

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


    @Override
    public void run() {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String s = reader.readLine();
            System.out.println("收到连接的客户端:ip="+socket.getInetAddress()+"  port:"+socket.getPort()+"  s="+s);
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            writer.write("服务端收到的数据为[" + s + "]\n");
            writer.flush();
            writer.close();
            reader.close();
            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
View Code

  服务端:

package com.wfd360.com.socketThread;

import com.wfd360.com.socketThread.thread.HandleServerThread;

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

/**
 * @Copyright (C) 
 * @Author: LI DONG PING
 * @Date: 2019-09-01 15:14
 * @Description:
 */
public class ServerSocketDemo {
    static int port = 1103;

    /**
     * 服务端开启多线程
     *
     * @param args
     */
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(port);
        int i=1;
        System.out.println("服务端已启动----"+i);
        while (true) {
            System.out.println("等待客户端连接---"+i);
            Socket socket = server.accept();
            System.out.println("已连接---"+i);
            HandleServerThread thread = new HandleServerThread(socket);
            thread.start();
            i++;
        }
    }
}
View Code

  客户端:

package com.wfd360.com.socketThread;

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

/**
 * @Copyright (C) 
 * @Author: LI DONG PING
 * @Date: 2019-09-01 15:50
 * @Description:
 */
public class ClientSocketDemo {
    static String host = "192.168.0.103";
    static Integer port = 1103;

    /**
     * 客户端设计逻辑:
     * 1.创建socket通信,设置IP和端口
     * 2.建立IO输出流,向服务端发送数据
     * 3.建立IO输入流,读取服务端应答的数据
     *
     * @param args
     */
    public static void main(String[] args) {
        Socket socket = null;
        BufferedWriter writer = null;
        BufferedReader reader = null;
        try {

            while (true) {
                //1.创建socket通信
                socket = new Socket(host, port);
                //2.建立IO输出流,向服务端发送数据
                writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                //读取控制台输入的数据
                System.out.print("请输入要发送的数据(结束请输入exit):");
                String sysIn = new BufferedReader(new InputStreamReader(System.in)).readLine();
                System.out.println("sysIn=" + sysIn);
                if ("exit".equals(sysIn)) {
                    break;
                }
                //注意这里必须加\n,因为是按照行读取
                writer.write("向服务端发送数据:" + sysIn + "\n");
                writer.flush();
                //3.建立IO输入流,读取服务端应答的数据
                reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String s = reader.readLine();
                System.out.println("客户端收到数据:" + s);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
                if (writer != null) {
                    writer.close();
                }
                if (socket != null) {
                    socket.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
View Code

5.socket下的多线程文件传输

  多线程处理类

package com.wfd360.com.socketFile.thread;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.net.Socket;

public class HandleServerThread extends Thread {
    private Socket socket;

    public HandleServerThread() {

    }

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

    /**
     * 将文件保存到本地
     */
    @Override
    public void run() {
        try {
            //需要写入的文件
            File file = new File("E:\\test\\c.txt");
            file.createNewFile();

            //处理流 输入
            DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
            String fileName = dataInputStream.readUTF();
            long fileSize = dataInputStream.readLong();
            System.out.println("fileName=" + fileName + ",fileSize=" + fileSize);
            //处理流 输出
            DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream(file));

            //采用字节数组读取文件内容
            byte[] bytes = new byte[128];
            int readSize = dataInputStream.read(bytes, 0, bytes.length);
            System.out.println("readSize=" + readSize);
            while (readSize != -1) {
                //写入本地文件
                dataOutputStream.write(bytes, 0, readSize);
                dataOutputStream.flush();
                readSize = dataInputStream.read(bytes, 0, bytes.length);
                System.out.println("readSize=" + readSize);
            }
            System.out.println("========文件上传完成==========");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
View Code

  服务端

package com.wfd360.com.socketFile;

import com.wfd360.com.socketFile.thread.HandleServerThread;

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

/**
 * @Copyright (C) 四川千行你我科技有限公司
 * @Author: LI DONG PING
 * @Date: 2019-09-01 15:14
 * @Description:
 */
public class ServerSocketDemo {
    static int port = 1103;

    /**
     * 服务端开启多线程
     *
     * @param args
     */
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(port);
        int i=1;
        System.out.println("服务端已启动----"+i);
        while (true) {
            System.out.println("等待客户端连接---"+i);
            Socket socket = server.accept();
            System.out.println("已连接---"+i);
            HandleServerThread thread = new HandleServerThread(socket);
            thread.start();
            i++;
        }
    }
}
View Code

  客户端

package com.wfd360.com.socketFile;

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

/**
 * @Copyright (C) 四川千行你我科技有限公司
 * @Author: LI DONG PING
 * @Date: 2019-09-01 15:50
 * @Description:
 */
public class ClientSocketDemo {
    static String host = "192.168.0.103";
    static Integer port = 1103;

    /**
     * 客户端设计逻辑:
     * 1.创建socket通信,设置IP和端口
     * 2.建立IO输出流,向服务端发送数据
     * 3.建立IO输入流,读取服务端应答的数据
     *
     * @param args
     */
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket(host, port);
        //准备上传文件
        File file = new File("E:\\test\\a.txt");
        DataInputStream dataInputStream = new DataInputStream(new FileInputStream(file));
        //准备输出 处理流
        DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
        dataOutputStream.writeUTF(file.getName());
        dataOutputStream.flush();
        dataOutputStream.writeLong(file.length());
        dataOutputStream.flush();
        //准备以字节的形式输出
        byte[] bytes = new byte[128];
        int readSize = dataInputStream.read(bytes, 0, bytes.length);
        while (readSize != -1) {
            System.out.println("readSize=" + readSize);
            dataOutputStream.write(bytes, 0, readSize);
            dataOutputStream.flush();
            readSize = dataInputStream.read(bytes, 0, bytes.length);
        }
        System.out.println("-----完成-------");
        dataInputStream.close();
        //当关闭的时候,服务端才会停止监听
        dataOutputStream.close();
    }
}
View Code

6.UDP的socket

  服务端

package com.wfd360.com.socketUDP;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

public class UDPServer {
    /**
     * 一、DatagramPacket类:
     *
     * 如果把DatagramSocket比作创建的港口码头,那么DatagramPacket就是发送和接收数据的集装箱。
     * 构造函数:一个用来接收数据,一个用来发送数据
     * public DatagramPacket(byte[] buf,int length) //接收数据
     * 构造 DatagramPacket 用来接收长度为 ilength 的包。
     * public DatagramPacket(byte[] buf,int length,InetAddress address,int port)
     * 构造数据报文包用来把长度为 ilength 的包传送到指定宿主的指定的端口号。
     * getAddress()
     * 返回接收或发送此数据报文的机器的 IP 地址。
     * getData()
     * 返回接收的数据或发送出的数据。
     * getLength()
     * 返回发送出的或接收到的数据的长度。
     * getPort()
     * 返回接收或发送该数据报文的远程主机端口号。
     *
     * 二、DatagramSocket类
     *
     * 此类表示用来发送和接收数据报包的套接字。 数据报套接字是包投递服务的发送或接收点。
     * DatagramSocket(int port)     创建数据报套接字并将其绑定到本地主机上的指定端口。
     * DatagramSocket(int port, InetAddress laddr)     创建数据报套接字,将其绑定到指定的本地地址。
     *
     * receive(DatagramPacket p)
     *              从此套接字接收数据报包。
     * void send(DatagramPacket p)
     *              从此套接字发送数据报包。
     * bind(SocketAddress addr)
     *              将此 DatagramSocket 绑定到特定的地址和端口。
     * void close()
     *              关闭此数据报套接字。
     * void connect(InetAddress address, int port)
     *              将套接字连接到此套接字的远程地址。
     * void connect(SocketAddress addr)
     *              将此套接字连接到远程套接字地址(IP 地址 + 端口号)。
     * void disconnect()
     *              断开套接字的连接。
     * getInetAddress()
     *              返回此套接字连接的地址。
     * InetAddress getLocalAddress()
     *              获取套接字绑定的本地地址。
     *
     * 三、InetAddress类
     * InetAddress用于表示计算机IP地址的一个类,而在日常应用中的IP地址用"192.168.0.1",
     * "WWW.it315.org"等字符串格式表示的。
     * getByName方法
     * getHostAddress方法
     * @param args
     */
    public static void main(String[] args) throws Exception {
        int port=1001;
        String host="192.168.0.103";


        //1.创建服务端 DatagramSocket(int port, InetAddress laddr)     创建数据报套接字,将其绑定到指定的本地地址。
        DatagramSocket datagramSocket = new DatagramSocket(port);
        System.out.println("服务已开启-----");
        //2.接收数据
        byte[] bytes=new byte[128];
        DatagramPacket datagramPacket =new DatagramPacket(bytes,0,bytes.length) ;
        System.out.println("-----等待接收数据");
        datagramSocket.receive(datagramPacket);
        InetAddress address = datagramPacket.getAddress();
        int port1 = datagramPacket.getPort();
        int length = datagramPacket.getLength();
        byte[] data = datagramPacket.getData();
        String s = new String(data);
        String format = String.format("address=%s,port=%s,length=%s,data=%s", address, port1, length, s);
        System.out.println(format);
        //3.发送数据包
        String sendData="发送数据-"+s;
        byte[] bytes1 = sendData.getBytes();
        InetAddress byName = InetAddress.getByName(host);
        DatagramPacket datagramPacketSend =new DatagramPacket(bytes1,0,bytes1.length,byName,1002) ;
        datagramSocket.send(datagramPacketSend);
    }
}
View Code

  客户端

package com.wfd360.com.socketUDP;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

public class UDPClient {
    public static void main(String[] args) throws Exception {
        int port=1002;
        String host="192.168.0.103";


        //1.创建服务端 DatagramSocket(int port, InetAddress laddr)     创建数据报套接字,将其绑定到指定的本地地址。
        DatagramSocket datagramSocket = new DatagramSocket(port);

        //3.发送数据包
        String sendData="你好吗?";
        byte[] bytes1 = sendData.getBytes();
        InetAddress byName = InetAddress.getByName(host);
        DatagramPacket datagramPacketSend =new DatagramPacket(bytes1,0,bytes1.length,byName,1001) ;
        datagramSocket.send(datagramPacketSend);
        //2.接收数据
        byte[] bytes=new byte[128];
        DatagramPacket datagramPacket =new DatagramPacket(bytes,0,bytes.length) ;
        System.out.println("-----等待接收数据");
        datagramSocket.receive(datagramPacket);
        InetAddress address = datagramPacket.getAddress();
        int port1 = datagramPacket.getPort();
        int length = datagramPacket.getLength();
        byte[] data = datagramPacket.getData();
        String s = new String(data);
        String format = String.format("address=%s,port=%s,length=%s,data=%s", address, port1, length, s);
        System.out.println(format);


    }
}
View Code

  完美!

原文地址:https://www.cnblogs.com/newAndHui/p/11516554.html