Java中Socket网络通信

目录

  • 目录

    • 网络协议信息
    • InetAddress类的应用
    • URL类的应用
    • 基于TCP的Socket通信
    • 基于UDP的socket通信
    • Socket通信总结
    • markdown编辑器快捷键

网络协议信息

  • 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
时间: 2024-08-02 12:40:56

Java中Socket网络通信的相关文章

Java中Socket通信的知识回顾---学习笔记

两台计算机进行通信的基本前提: (1)IP地址: 每台计算机都有自己独一无二的IP地址,根据IP地址判断与哪台计算机进行通信. (2)端口号: 每个应用程序都有自己专属的端口,根据端口号判断与计算机中的哪个应用程序进行通信. 说明: <1>用于区分不同应用程序 <2>端口号的范围:0-65535,其中0-1023是为系统保留的端口号 <3>常用的协议的端口号: http:80 ftp:21 telnet:23 <4>IP地址+端口号=Socket,Socke

Java中socket接口调用

最近一个项目中接口通讯这一块主要是调用银联系统的socket接口,我方是客户端,即发送请求接收返回报文的一方.在贴代码之前,还是要了解一下关于socket的基础知识. Socket的基本概念 1.建立连接 当需要建立网络连接时,必须有一台机器运行一个程序,随时等候连接,而另一端的程序这对其发出连接请求.这一点同电话系统类似--必须有一方拨打电话,而另一方必须等候电话连通. 建立连接的过程为: (1)先在服务器端生成一个ServerSocket实例对象,随时监听客户端的连接请求. (2)当客户端需

java中socket创建服务端与客户端即时对聊

package tool; 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.ServerSocket; import java.net.Socket; impo

【Java基础学习笔记】Java中Socket+Swing设计简单通信

在<Java从入门到精通(第3版)>的原书中,客户端仅能发送一次数据,我在此基础上修改了一点点,实现了多次发送数据的单向通讯. 1. 服务器端 package Tcp_IP; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; import java.sq

java中socket网络通讯

服务器端代码: package socket; import java.io.IOException;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.io.BufferedReader;import java.io.InputStreamReader;import java.net.ServerSocket;import java.net.Socket; public class Server {

??Java中Socket上的Read操作阻塞问题

从Socket上读取对端发过来的数据一般有两种方法: 1)按照字节流读取 BufferedInputStream in = new BufferedInputStream(socket.getInputStream()); int r = -1; List<Byte> l = new LinkedList<Byte>(); while ((r = in.read()) != -1) { l.add(Byte.valueOf((byte) r)); } 2)按照字符流读取 Buffe

Java中Socket在发送请求的时候要分清print()和println()

近期在开发中需要一个功能,向第三方服务器发送我方数据的功能,对数据的封装格式要求特别严格,在组装数据完成后,发送给第三方服务器却怎么也通不过,查找了好久,也对比了对方给出来的数据样本,还是不行,后来检查代码和拦截发送的数据后才发现,在socket发送的时候,使用的是println()方法,这个方法会自动在数据的后面加上一个回车符,所以在对比数据的时候没有发现,改为print()后顺利通过了~~~

JAVA 中进行网络通信时,通信的程序两端要传输的对象,不仅要序列化,而且这个对象所属的类的名字要完全一样,连包的名字都得一样

如上图项目目录,这是一个简易的QQ,客户端登录的时候要传输用户信息到服务器验证,所以两端都会用到User类的对象,但一开始我在Server端的包名是com.qq.server.common,两端的报名字不一致,所以server端卡在了逆序列化那里: User user=(User)ois.readObject(); 也就是说server端收到了传输过来的user对象,但是无法解析,当时报的错误有两种,(虽然当时知道了问题出在哪里,不知道为什么会报不同的错误,就在把这种迷惑记录在案的时候突然似乎明

Java中的Socket的用法

                               Java中的Socket的用法 Java中的Socket分为普通的Socket和NioSocket. 普通Socket的用法 Java中的网络通信时通过Socket实现的,Socket分为ServerSocket和Socket两大类,ServerSocket用于服务器端,可以通过accept方法监听请求,监听请求后返回Socket,Socket用于完成具体数据传输,客户端也可以使用Socket发起请求并传输数据.ServerSocke