Java中Socket网络通信

Posted java小龙菜鸟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中Socket网络通信相关的知识,希望对你有一定的参考价值。

目录


网络协议信息

  • TCP 传输控制协议(Transmission Control Protocol)
  • IP 互联网协议(Internet Protocol)
  • HTTP 超文本传输协议(默认端口号为80)
  • FTP 文件传输协议(默认端口号为:21)
  • Telnet (远程登录服务,默认端口号为:23)

InetAddress类的应用

用于标识网络上的硬件资源(表示标识ip地址),InetAddress的实例对象包含以数字形式保存的IP地址,同时还可能包含主机名(如果使用主机名来获取InetAddress的实例,或者使用数字来构造,并且启用了反向主机名解析的功能)。InetAddress类提供了将主机名解析为IP地址(或反之)的方法。

代码块

    /*用于网络上的硬件资源,表示互联网协议(IP)地址**/
    public static void main(String[] args) throws UnknownHostException {

        //获取本机的InetAddress实列
        InetAddress address = InetAddress.getLocalHost();
        //获取本机名称
        System.out.println("计算机名称:"+address.getHostName());
        //获取本机IP
        System.out.println("本机IP地址:"+address.getHostAddress());
        //获取本机IP地址的字节数组形式
        byte[] bytes=address.getAddress();
        System.out.println("本机IP地址的字节数组形式:"+Arrays.toString(bytes));
        //直接输出InetAddress对象
        System.out.println(address);

        System.out.println("------------------------------");
        //根据主机名获取InetAddress实列
        //InetAddress address2=InetAddress.getByName("XLP007");
        //根据ip地址获取InetAddress实列
        InetAddress address2=InetAddress.getByName("192.168.0.126");

        //获取其他主机名称
        System.out.println("计算机名称:"+address2.getHostName());
        //获取其他主机IP地址
        System.out.println("IP地址名称:"+address2.getHostAddress());
        //IP地址的字节数组形式
        //byte[] bytes2=address.getAddress();
        //System.out.println("IP地址的字节数组形式:"+Arrays.toString(bytes2));
        //直接输出InetAddress对象
        //System.out.println(address2);
    }

URL类的应用

1.Uniform Resource Locator 统一资源定位符,表示Internet上某一资源的地址;
2.URL由两部分组成:协议名称和资源名称,中间用冒号隔开;
3.在java.net包中,提供了URL类来表示URL,通过URL可以直接读取或写入网络上的数据;

代码块:通过URL获取信息

    public static void main(String[] args) {

        try {
            //创建一个URL实例
            URL bd = new URL("http://www.baidu.com");
            //通过父节点获取URL实例(?后面的是参数,#后面的锚点)
            URL url=new URL(bd,"/index.html?userName=lixiaolong#test");
            //获取协议
            System.out.println("协议: "+url.getProtocol());
            //获取主机
            System.out.println("主机: "+url.getHost());
            //获取文件
            System.out.println("文件: "+url.getFile());
            //获取端口号(如果未指定端口号,则使用默认的端口号,但是getPort()方法返回的
            //是-1,getDefaultPort()方法返回默认端口号)
            System.out.println("端口号: "+url.getPort());
            System.out.println("默认端口号: "+url.getDefaultPort());
            //获取文件路径
            System.out.println("文件路径: "+url.getPath());
            //获取参数
            System.out.println("参数: "+url.getQuery());
            //获取锚点
            System.out.println("锚点: "+url.getRef());

        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

基于TCP的Socket通信

简介:TCP协议是面向连接、可靠的、有序的,以字节流的方式发送数据

基于TCP协议实现网络通信的类
- 客户端的Socket类
- 服务端的ServerSocket类

Socket通信实现步骤

1.分别在服务端和客户端创建ServerSocket和Socket
2.打开连接到Socket的输入/输出流
3.按照协议对Socket进行读/写操作
4.关闭输入输出流,关闭Socket(千万不要忘记这一步)

代码块:基于Tcp协议的Socket通信,实现用户登录

server.java
    public static void main(String[] args) {
        try {
            //1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
            //(注意,要1023以后的端口,因为1023以前的端口已经用于通用的应用中了)
            ServerSocket serverSocket=new ServerSocket(8989);
            //2.调用accept()方法开始监听,等待客户端的连接
            System.out.println("*****服务器即将启动,等待客户端的连接******");
            //返回一个Socket对象给客户端
            Socket socket = serverSocket.accept();
            //3.获取输入流对象,并读取客户端信息
            InputStream is = socket.getInputStream();//字节输入流
            //将字节输入流转换为字符输入流
            InputStreamReader isr=new InputStreamReader(is);
            //将字符输入流放入缓冲中
            BufferedReader br=new BufferedReader(isr);
            //定义一个变量保存读取客户端的信息
            String msg=null;
            //5.循环读取客户端的信息
            while((msg=br.readLine())!=null){
                System.out.println("我是服务器,客户端的信息是:"+msg);
            }

            //关闭输入流对象
            socket.shutdownInput();

            //4.创建输出流,响应客服端的请求
            OutputStream os=socket.getOutputStream();
            //创建打印输出流,包装输出流
            PrintWriter pw=new PrintWriter(os);
            //输出一句话
            pw.write("客户端,欢迎您!!");
            //调用flush()方法刷新缓冲
            pw.flush();

            //关闭相关资源
            pw.close();
            os.close();
            br.close();
            isr.close();
            is.close();
            socket.close();
            serverSocket.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    client.java
        public static void main(String[] args) {
            try {
                //1.创建客户端Socket,指定服务器地址和端口号
                Socket socket=new Socket("localhost",8989);
                //获取输出流对象,向服务器端发送信息
                OutputStream os=socket.getOutputStream();//字节输出流
                //将字节输出流对象转换为打印输出流对象
                PrintWriter pw=new PrintWriter(os);
                pw.write("用户名:admin;密码:123456");
                //调用flush来刷新缓冲
                pw.flush();

                //关闭输出流(一定要放在这里)
                socket.shutdownOutput();

                //创建输入流输出服务器端响应的信息
                InputStream is=socket.getInputStream();
                //将字节输入流对象转换为字符输入流对象
                InputStreamReader isr=new InputStreamReader(is);
                //创建BufferedReader来包装输入流
                BufferedReader br=new BufferedReader(isr);

                //定义一个变量保存响应的信息
                String msg=null;
                //循环读取服务器响应的信息
                while((msg=br.readLine()) !=null){
                    System.out.println("我是客户端,服务器说: "+msg);
                }

                //关闭相关资源
                br.close();
                isr.close();
                is.close();
                pw.close();
                os.close();
                socket.close();

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

代码块:引用多线程应用实现多个用户访问服务器

serverThread.java(多线程)

    //定义一个Socket对象
    Socket socket=null;

    //定义一个构造方法创建实例
    public ServerThread(Socket socket){
        this.socket=socket;
    }

    //定义线程执行操作,响应客户端的请求
    public void run(){
        //3.获取输入流对象,并读取客户端信息
        InputStream is=null;
        //将字节输入流转换为字符输入流
        InputStreamReader isr=null;
        //将字符输入流放入缓冲中
        BufferedReader br=null;
        //4.创建输出流,响应客服端的请求
        OutputStream os=null;
        //创建打印输出流,包装输出流
        PrintWriter pw=null;

        try {
            is = socket.getInputStream();
            isr = new InputStreamReader(is);
            br = new BufferedReader(isr);
            //定义一个变量保存读取客户端的信息
            String msg=null;
            //5.循环读取客户端的信息
            while((msg=br.readLine())!=null){
                System.out.println("我是服务器,客户端的信息是:"+msg);
            }
            //关闭输入流对象
            socket.shutdownInput();
            os = socket.getOutputStream();
            pw = new PrintWriter(os);
            //输出一句话
            pw.write("客户端,欢迎您!!");
            //调用flush()方法刷新缓冲
            pw.flush();

        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            //因为相关资源一定要关闭,所以房租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 e) {
                e.printStackTrace();
            }
        }
    }

----------
    ServerSocketThread.java(服务器端)
        public static void main(String[] args) {
            try {
                //1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
                //(注意,要1023以后的端口,因为1023以前的端口已经用于通用的应用中了)
                ServerSocket serverSocket=new ServerSocket(8989);
                Socket socket =null;
                //定义一个变量保存客户端的数量
                int count=0;

                //2.调用accept()方法开始监听,等待客户端的连接
                System.out.println("*****服务器即将启动,等待客户端的连接******");

                //因为多线程,所以要循环监听和等待客户端的连接
                while(true){
                    //调用accept()方法循环监听客户端,并响应客户端
                     socket=serverSocket.accept();
                    //创建一个新的线程
                    ServerThread serverThread=new ServerThread(socket);
                    //执行线程
                    serverThread.start();
                    //输出访问服务器客户端的ip地址
                    InetAddress address=socket.getInetAddress();
                    System.out.println("当前的IP地址为: "+address.getHostAddress());
                    //输出访问该服务器的客户端的数量
                    count++;
                    System.out.println("当前访问服务器的数量为: "+count);
                }

                //因为是多线程,所以socket不能关闭
                //serverSocket.close();

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

----------
    ClientSocketThread.java(客户端)
        public static void main(String[] args) {
            try {
                //1.创建客户端Socket,指定服务器地址和端口号
                Socket socket=new Socket("localhost",8989);
                //获取输出流对象,向服务器端发送信息
                OutputStream os=socket.getOutputStream();//字节输出流
                //将字节输出流对象转换为打印输出流对象
                PrintWriter pw=new PrintWriter(os);
                pw.write("用户名:张三;密码:123456");
                //调用flush来刷新缓冲
                pw.flush();

                //关闭输出流(一定要放在这里)
                socket.shutdownOutput();

                //创建输入流输出服务器端响应的信息
                InputStream is=socket.getInputStream();
                //将字节输入流对象转换为字符输入流对象
                InputStreamReader isr=new InputStreamReader(is);
                //创建BufferedReader来包装输入流
                BufferedReader br=new BufferedReader(isr);

                //定义一个变量保存响应的信息
                String msg=null;
                //循环读取服务器响应的信息
                while((msg=br.readLine()) !=null){
                    System.out.println("我是客户端2,服务器说: "+msg);
                }

                //关闭相关资源
                br.close();
                isr.close();
                is.close();
                pw.close();
                os.close();
                socket.close();

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

基于UDP的socket通信

1.简介

1.基本介绍:UDP协议(用户数据报协议)是无连接、不可靠的、无序的,速度相对比较快,以数据报为载体
2.UDP是如何传输的:进行数据传输时,首先需要将要传输的数据定义成数据报(Datagram),在数据报中指明数据报 要达到的Socket(主机地址和端口号),然后再将数据报发送出去

2.相关通信类

DatagramPacket:数据报类
DatagramSocket:进行端到端通信的类

3.实现步骤

1.服务器端实现步骤
①创建DatagramSocket,指定相应的端口号
②创建DatagramPacket,用来接受客户端发送的数据
③接受客户端发送的数据信息
④读取数据

2.客户端实现步骤
    ①定义发送的信息(服务器的地址,端口号以及内容)
    ②创建DatagramPacket,包含要发送的信息
    ③创建DatagramSocket,用来实现数据的发送
    ④发送数据

代码块:实现基于UDP的用户登录通信

    Server.java(服务器端)
    public static void main(String[] args) throws IOException {
        /**
         * 接收客户端发送的数据
         * */
        //1.创建DatagramSocket对象,指定服务器的端口
        DatagramSocket socket=new DatagramSocket(8989);

        //2.创建DatagramPacket对象,指定接受客户端发送的信息
        //首先创建一个字节保存信息
        byte[] data=new byte[1024];
        DatagramPacket packet=new DatagramPacket(data,data.length);

        //3.接受客户端发送的信息
        System.out.println("*****服务器已经启动,等待客户端发送数据****");
        socket.receive(packet);//此方法在接收到数据之前会一直处在阻塞状态

        //4.读取数据
        String info=new String(data, 0, packet.getLength());
        System.out.println("我是服务器,客户端说: "+info);

        /**
         * 响应客户端的请求
         * 
         * */
        //1.定义响应客户端的地址、端口号、数据
        //通过数据报获取客户端的地址
        InetAddress address=packet.getAddress();
        //通过数据报获取客户端的端口号
        int port=packet.getPort();
        //定义发送的数据
        byte[] data2="欢迎您!".getBytes();

        //2.创建数据报,来保存要响应客户端的信息
        DatagramPacket packet2=new DatagramPacket(data2, data2.length, address, port);

        //3.调用Socket
        socket.send(packet2);

        //4.千万不要忘记关闭相关资源
        socket.close();
    }

----------
    client.java(客户端)
        public static void main(String[] args) throws IOException {

            /**
             * 发送信息到服务器
             * */
            //1.定义发送的信息(服务器地址,端口号)
            //定义服务器地址
            InetAddress address=InetAddress.getByName("localhost");
            //定义端口号
            int port=8989;
            //定义要发送的内容,要用字节来
            byte[] data="用户名:张三;密码:123456".getBytes();

            //2.创建DatagramPacket对象保存客户端要发送的数据
            DatagramPacket packet=new DatagramPacket(data, data.length, address, port);

            //3.创建DatagramSocket发送数据
            DatagramSocket socket=new DatagramSocket();

            //4.发送数据
            socket.send(packet);

            /**
             * 接收服务器响应的信息
             * */
            //1.创建DatagramPacket对象,接收服务器发送的信息
            byte[] data2=new byte[1024];
            DatagramPacket packet2=new DatagramPacket(data2,0,data2.length);

            //2.接收服务器发送的信息
            socket.receive(packet2);

            //3.读取服务器发送的信息
            String info=new String(data2,0,packet.getLength());
            System.out.println("我是客户端,服务器说: "+info);

            //4.关闭资源(千万不要忘记了)
            socket.close();
    }

代码块:引用多线程实现多个用户访问服务器

ServerThread.java(多线程)
    //定义一个DatagramSocket对象
    private DatagramSocket socket;
    private DatagramPacket packet;

    //定义一个构造函数初始化对象
    public ServerThread(DatagramSocket socket,DatagramPacket packet){
        this.socket=socket;
        this.packet=packet;
    }

    //定义一个线程执行方法
    public void run(){

        try {
            /**
             * 接收客户端发送的数据
             * */
            //1.读取数据
            String info=new String(packet.getData(), 0, packet.getLength());
            System.out.println("我是服务器,客户端说: "+info);

            /**
             * 响应客户端的请求
             * 
             * */
            //1.定义响应客户端的地址、端口号、数据
            //通过数据报获取客户端的地址
            InetAddress address=packet.getAddress();
            System.out.println("当前客户端的IP地址为: "+address);
            //通过数据报获取客户端的端口号
            int port=packet.getPort();
            //定义发送的数据
            byte[] data2="欢迎您!".getBytes();

            //2.创建数据报,来保存要响应客户端的信息
            DatagramPacket packet2=new DatagramPacket(data2, data2.length, address, port);

            //3.调用Socket
            socket.send(packet2);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
----------
    UDPServerThread.java(服务器端)
    public static void main(String[] args) throws IOException {

        /**
         * 接收客户端发送的数据
         * */
        //1.创建DatagramSocket对象,指定服务器的端口,初始化DatagramSocket对象
        DatagramSocket socket=new DatagramSocket(8989);
        //定义一个变量保存客户端的数量
        int count=0;
        System.out.println("*****服务器已经启动,等待客户端的连接****");

        //因为多线程,所以要循环监听和等待客户端的连接
        while(true){
            byte[] data=new byte[1024];

            //创建一个DatagramPacket对象,保存从客户端接收的数据
            DatagramPacket packet=new DatagramPacket(data,0,data.length);
            //此时处于阻塞状态,等待客户端请求
            socket.receive(packet);
            //创建一个新的线程
            ServerThread serverThread=new ServerThread(socket,packet);
            // 未设置优先级可能会导致运行时速度非常慢,可降低优先级
            serverThread.setPriority(4);
            //启动线程
            serverThread.start();
            //访问服务器的客户端的数量
            count++;
            System.out.println("当前访问服务器的客户端的数量为: "+count);
        }
    }
----------
    UDPClientThread.java(客户端)
        public static void main(String[] args) throws IOException {
            /**
             * 发送信息到服务器
             * */
            //1.定义发送的信息(服务器地址,端口号)
            //定义服务器地址
            InetAddress address=InetAddress.getByName("localhost");
            //定义端口号
            int port=8989;
            //定义要发送的内容,要用字节来
            byte[] data="用户名:李四;密码:123456".getBytes();

            //2.创建DatagramPacket对象保存客户端要发送的数据
            DatagramPacket packet=new DatagramPacket(data, data.length, address, port);

            //3.创建DatagramSocket发送数据
            DatagramSocket socket=new DatagramSocket();

            //4.发送数据
            socket.send(packet);

            /**
             * 接收服务器响应的信息
             * */
            //1.创建DatagramPacket对象,接收服务器发送的信息
            byte[] data2=new byte[1024];
            DatagramPacket packet2=new DatagramPacket(data2,0,data2.length);

            //2.接收服务器发送的信息
            socket.receive(packet2);

            //3.读取服务器发送的信息
            String info=new String(data2,0,packet.getLength());
            System.out.println("我是客户端1,服务器说: "+info);

            //4.关闭资源(千万不要忘记了)
            socket.close();
        }

Socket通信总结

1.多线程的优先级
2.关闭流问题与socket关闭问题
3.传递对象
4.传递文件


markdown编辑器快捷键

  • 加粗 Ctrl + B

  • 斜体 Ctrl + I

  • 引用 Ctrl + Q

  • 插入链接 Ctrl + L

  • 插入代码 Ctrl + K

  • 插入图片 Ctrl + G

  • 提升标题 Ctrl + H

  • 有序列表 Ctrl + O

  • 无序列表 Ctrl + U

  • 横线 Ctrl + R

  • 撤销 Ctrl + Z

  • 重做 Ctrl + Y

以上是关于Java中Socket网络通信的主要内容,如果未能解决你的问题,请参考以下文章

java 界面编程用socket实现服务端与客户端的循环通信。

Java 网络编程

Java Socket Server与Python客户端的通信,程序不会输入“inputLine = in.readLine()” - 循环

JAVA服务器与客户端的socket通信问题

Java语言 网络编程之Socket用法

Java Socket通信介绍及可能遇到的问题解决_java - JAVA