zoukankan      html  css  js  c++  java
  • Java 使用UDP、TCP进行网络通信

    UDP

    工具类

    public class UDP {
        private static final int port = 9000;  //要使用的端口号
    
        /**
         * 发送消息
         * @Param ip 对方的ip,String
         * @Param msg 要发送的消息,String类型
         */
        public static void send(String ip,String msg) throws IOException {
            //对方的ip,不能直接用String,需要转换一下
            InetAddress ipAddr = InetAddress.getByName(ip);
    
            //socket,相当于码头
            DatagramSocket socket = new DatagramSocket();
    
            // packet,数据包,相当于集装箱
            // 参数:byte[]、数据长度、对方ip(不能直接写String)、要使用的端口号
            // 什么类型都可以传输,比如传文件,不局限于String,因为都要转换为字节数组
            DatagramPacket packet = new DatagramPacket(msg.getBytes(), msg.length(),ipAddr,port);
    
            //通过socket发送packet
            socket.send(packet);
            System.out.println("send:"+msg);
    
            //关闭socket
            socket.close();
        }
    
    
        /**
         *监听端口,接收消息
         */
        public static void receive() throws IOException {
            //socket,指定要监听的端口。发送、接收使用的端口要相同
            DatagramSocket socket = new DatagramSocket(port);
    
            // packet,用一个byte[]来存储数据
            // 第一个数值是字节数组的长度,第二个数值是要读取的字节数,把读取到的数据放到byte[]中
            // 读取的字节数要小于等于byte[]的长度,不然放不下
            DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
    
            //一直监听
            while (true){
                socket.receive(packet); //通过socket接收packet,用packet来封装接收到的数据,没接收到数据时会一直阻塞
                byte[] data = packet.getData(); //获取packet中的数据(整个byte[])
                int length = packet.getLength(); //获取数据的实际长度。packet中的byte[]不一定是装满的,需要获取实际的字节数
    
                String msg = new String(data, 0, length); //byte[]、offset、length
                // msg = new String(data); //其实不获取实际长度也行
                System.out.println("received:"+msg);
    
                //获取本机ip、发送方ip
                // InetAddress localAddress = socket.getLocalAddress(); //本机
                // InetAddress address = packet.getAddress();  //发送方
                // String ip = address.getHostAddress(); //String类型的ip
    
                // socket.close();  //关闭socket
                //一直监听,不关闭socket
                // 退出聊天时,比如退出桌面程序或web项目点击“结束聊天”、超过2分钟未互动,需要关闭socket
    
            }
        }
    
    }

    UDP不区分客户端、服务端,2边使用的socket都是DatagramSocket,使用的packet都是DatagramPacket。发送、接收可以使用同一个socket。

    发送消息

    public class Send {
        public static void main(String[] args) throws IOException {
            UDP.send("127.0.0.1", "hello");
        }
    }

    接收消息

    public class Receive {
        public static void main(String[] args) throws IOException {
            UDP.receive();
        }
    }

    先启动接收方,再启动发送方。

    有一个问题:写了2个主类,分别启动,一般不这么干,使用多线程代替。

    测试类

    public class Test {
        public static void main(String[] args) throws IOException, InterruptedException {
            //开启一条线程,监听端口、接收消息
            Thread receiveThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        UDP.receive();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
            receiveThread.start();
    
            //怕接收线程暂时没分配到时间片,在发送消息之后才执行,没能接收到掐前面的消息,可以让发送消息的线程沉睡会儿
            Thread.sleep(100);
    
            //也可以单独开启一条线程来发送消息
            UDP.send("127.0.0.1","hello");
        }
    }

    UDP是不可靠的,不管对方ip存不存在、对方有没有启动监听,直接发出去,不管对方能不能接收到。


    TCP

    工具类

    public class TCP {
        private static final int port = 9000;  //要使用的端口号
    
        /**
         * 发送消息
         * @Param ip 对方的ip,String
         * @Param msg 要发送的消息,String类型
         */
        public static void send(String ip,String msg) throws IOException {
            //客户端的socket。直接使用String类型的对方的ip
            Socket socket = new Socket(ip, port);
    
            //向服务端发送数据
            OutputStream os = socket.getOutputStream(); //输出流
            os.write(msg.getBytes()); //byte[]
            System.out.println("send:"+msg);
        }
    
    
        /**
         *监听端口,接收消息
         */
        public static void receive() throws IOException {
            //服务端的socket,指定要监听的端口
            ServerSocket serverSocket = new ServerSocket(port);
    
            //一直监听
            while (true) {
                //接收客户端的请求,并创建一个与之对应的Socket来与该客户端通信
                Socket socket = serverSocket.accept();
    
                //接收客户端发送的数据
                InputStream is = socket.getInputStream();
                byte[] buff = new byte[1024];
                int length = is.read(buff); //将数据读取到byte[]中,返回读取到的字节数
                java.lang.String msg = new java.lang.String(buff, 0, length); //有很多个String类,不要导错了
                System.out.println("received:" + msg);
    
                // 获取本机ip、发送方ip
                // InetAddress localAddress = socket.getLocalAddress();  //本机
                // InetAddress inetAddress = socket.getInetAddress();  //发送方// String ipAddress = localAddress.getHostAddress(); //获取String类型的IP
    
                // socket.close();
                
            }
        }
    
    }

    TCP要区分客户端、服务端,客户端用Socket,服务端用ServerSocket,通过ServerSocket获取与客户端对应的socket,来与客户端通信。

    客户端、服务端是相对的,发送数据的一方叫做客户端,接收消息的一方叫做服务端,一般都要客户端、服务端。

    接收到对方消息后,可以调用send()传入对方ip与之通信,也可以写个重载的send(),传入与客户端对应的socket。

    测试类

    public class Test {
        
        public static void main(String[] args) throws IOException, InterruptedException {
            //开启一条线程,监听端口、接收消息
            Thread receiveThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        TCP.receive();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
            receiveThread.start();
    
            //怕接收线程暂时没分配到时间片,在发送消息之后才执行,没能接收到掐前面的消息,可以让发送消息的线程沉睡会儿
            Thread.sleep(100);
    
            //也可以单独开启一条线程来发送消息
            TCP.send("127.0.0.1","hello");
        }
        
    }

    TCP是可靠的,三次握手确定双方可以正常通信。

  • 相关阅读:
    内容页超连接关键词的完美实现
    鼠标经过文字链接时出现漂亮的提示层
    简单的jQuery检测注册用户名
    触发Repeater中的Dropdownlist的SelectedIndexChanged如何获得Repeater的当前行
    读取XML的节点属性并绑定到ListBox
    第十八章 6string型字符串的替换 简单
    第十八章 2string字符串 简单
    第十七章 特殊成员_函数指针也可以做为参数 简单
    第十七章 特殊成员_类的函数指针 简单
    第十七章 特殊成员_成员函数指针数组 简单
  • 原文地址:https://www.cnblogs.com/chy18883701161/p/12556339.html
Copyright © 2011-2022 走看看