java实现UDP及TCP通信

简介: java实现UDP及TCP通信,UDP(User Datagram Protocol)用户数据报协议,TCP(Transmission Control Protocol) 传输控制协议,是传输层的两个重要协议。

简介

UDP(User Datagram Protocol)用户数据报协议,TCP(Transmission Control Protocol) 传输控制协议,是传输层的两个重要协议。

UDP是一种无连接、不可靠传输的协议。其将数据源IP、目的地IP和端口封装成数据包,不需要建立连接,每个数据包的大小限制在64KB内;发送不管对方是否准备好,接收方收到也不确认,故是不可靠的;可以广播发送,发送数据结束时无需释放资源,开销小,速度快。UDP协议适合于即时通信场景,丢失少量数据包也不影响,例如语音通话、视频等。

TCP协议的使用必须双方先建立连接,即是一种面向连接的可靠通信协议。传输前,采用“三次握手”方式建立连接。在连接中可进行大数据量的传输 。连接、发送数据都需要确认,且传输完毕后,还需释放已建立的连接,通信效率较低。TCP协议适用于对信息安全要求较高的场景,例如文件下载等需要安全的数据通信。

Internet协议(IP)

Internet协议类 — InetAddress  ,主要包括以下API:

public static InetAddress getLocalHost()

返回本主机的地址对象

public static InetAddress getByName(String host)

得到指定主机的IP地址对象,参数是域名或者IP地址

public String getHostName()

获取此IP地址的主机名

public String getHostAddress()

返回IP地址字符串

public boolean isReachable(int timeout)

判断是否可在指定毫秒内连通该IP地址对应的主机

//本机ip
        InetAddress ip1=InetAddress.getLocalHost();
        System.out.println(ip1.getHostName());
        System.out.println(ip1.getHostAddress());
        //域名IP
        InetAddress ip2=InetAddress.getByName("www.baidu.com");
        System.out.println(ip2.getHostAddress());
        InetAddress ip3=InetAddress.getByName("112.80.248.75");
        System.out.println(ip3.getHostAddress());
        //判断是否可以连通 ping
        System.out.println(ip3.isReachable(5000));

使用UDP通信

假定从客户端(clientP)给服务端(serverP)发消息,我们先实现客户端发消息功能。

  1. 首先创建DatagramSocket对象socket,作为发送端UDP对象不需要定义端口号,使用随机分配的就可以了。
  2. 然后使用DatagramPacket:数据包对象,将我们的数据内容进行包装,在这里需要设置好接收端口号。
  3. 最后使用send方法把数据包发出去。
  4. 释放通信资源
DatagramSocket socket=new DatagramSocket();
        System.out.println("本机端口:"+socket.getLocalPort());//发送端端口号
        for (int i = 0; i < 5; i++) {
            //内容
            byte[] buff = ("你好 "+i).getBytes();
            DatagramPacket packet = new DatagramPacket(buff, buff.length,
                    InetAddress.getLocalHost(), 8888);//接收端口
            //发送
            socket.send(packet);
        }
        socket.close();

再来实现服务端接收功能。

  1. 首先也是创建DatagramSocket对象socket,作为接收端UDP对象就需要定义端口号了,与服务端一致。
  2. 然后使用DatagramPacket,数据包对象,来存放我们需要接收的内容数据包。
  3. 最后使用receive方法把数据包收回来。
DatagramSocket socket=new DatagramSocket(8888);
        for (int i = 0; i < 5; i++) {
            //内容
            byte[] buff = new byte[1024 * 10];
            DatagramPacket packet = new DatagramPacket(buff, buff.length);
            //接收
            socket.receive(packet);
            //数据
            int len = packet.getLength();//获取收到内容的长度
            String rs = new String(buff, 0, len);
            System.out.println("收到 " +packet.getSocketAddress().toString()+":"+ rs);
        }
        socket.close();

以上就实现了客户端往服务端发送消息。这个实现的还只是单方面通信,那我们如何实现互相通信呢。

实现UDP的C-S互通信

基于前面内容我们知道如何实现一方给另一方发消息,这里我们加一个线程进行反过来操作就实现了一个简单的互相通信。

  1. 服务端

我们设置一个线程来进行数据接收打印,在主线程进行数据发送,再根据关键字识别进行通信中断功能。

public class serverP {
    public static void main(String[] args) throws Exception {
        System.out.println("服务端+++");
        Thread t=new myThread();//服务端接收线程
        t.start();
        //发送 对象
        DatagramSocket socketp =new DatagramSocket();
        Scanner sc=new Scanner(System.in);
        while(true) {
            //内容
            String msg=sc.nextLine();
            byte[] buff = msg.getBytes();
            DatagramPacket packet = new DatagramPacket(buff, buff.length,
                    InetAddress.getLocalHost(), 8888);
            //接收
            socketp.send(packet);
            if("再见".equals(msg)) {
                socketp.close();
                System.out.println("断开连接~");
                break;
            }
        }
    }
}
/**
 * 接收线程
 */
class myThread extends Thread{
    @Override
    public void run() {
        //对象
        DatagramSocket socket= null;
        try {
            socket = new DatagramSocket(8889);
        } catch (SocketException e) {
            e.printStackTrace();
        }
        while (true) {
            //内容
            byte[] buff = new byte[1024 * 10];
            DatagramPacket packet = new DatagramPacket(buff, buff.length);
            //接收
            try {
                socket.receive(packet);
            } catch (IOException e) {
                e.printStackTrace();
            }
            //数据
            int len = packet.getLength();//获取收到内容的长度
            String rs = new String(buff, 0, len);
            System.out.println("收到 " +packet.getSocketAddress().toString()+
                    ":"+ rs);
            if("再见".equals(rs)) {
                socket.close();
                break;
            }
        }
    }
}
  1. 客户端,类似的有:
public class clientP {
    public static void main(String[] args) throws Exception {
        System.out.println("客户端+++");
        Thread t=new myThreadC();//服务端接收线程
        t.start();
        //发送 对象
        DatagramSocket socket=new DatagramSocket();
        Scanner sc=new Scanner(System.in);
        while(true) {
            //内容
            String msg=sc.nextLine();
            byte[] buff = msg.getBytes();
            DatagramPacket packet = new DatagramPacket(buff, buff.length,
                    InetAddress.getLocalHost(), 8889);
            //接收
            socket.send(packet);
            if("再见".equals(msg)) {
                socket.close();
                System.out.println("断开连接~");
                break;
            }
        }
    }
}
/**
 * 接收线程
 */
class myThreadC extends Thread{
    @Override
    public void run() {
        //对象
        DatagramSocket socket= null;
        try {
            socket = new DatagramSocket(8888);
        } catch (SocketException e) {
            e.printStackTrace();
        }
        while (true) {
            //内容
            byte[] buff = new byte[1024 * 10];
            DatagramPacket packet =  new DatagramPacket(buff, buff.length);
            //接收
            try {
                socket.receive(packet);
            } catch (IOException e) {
                e.printStackTrace();
            }
            //数据
            int len = packet.getLength();//获取收到内容的长度
            String rs = new String(buff, 0, len);
            System.out.println("收到 " +packet.getSocketAddress().toString()+":"+ rs);
            if("再见".equals(rs)) {
                socket.close();
                break;
            }
        }
    }
}
  1. 至此我们实现了UDP互相发消息

TCP通信

java中只要是使用java.net.Socket类实现通信,底层即是使用了TCP协议。

public Socket(String host , int port),创建发送端的Socket对象与服务端连接,参数为服务端程序的ip和端口。

方法:getOutputStream、getInputStream,分别是获得字节输出、输入流对象。

public ServerSocket(int port),注册服务端端口。

方法:accept,等待接收客户端的Socket通信连接,连接成功返回Socket对象与客户端建立端到端通信

具体来说,客户端发送实现:

  1. 创建客户端的Socket对象,请求与服务端的连接。
  2. 使用socket对象调用getOutputStream()方法得到字节输出流。
  3. 使用字节输出流完成数据的发送,发送一行内容就要flush。
  4. 释放资源:关闭socket管道。
Socket socket=new Socket("127.0.0.1",6666);
            OutputStream os= socket.getOutputStream();
            PrintStream ps=new PrintStream(os);
            while(true) {
                ps.println("hello~");
                ps.flush();
            }

服务端接收:

  1. 创建ServerSocket对象,注册服务端端口。
  2. 调用ServerSocket对象的accept()方法,等待客户端的连接,并得到Socket管道对象。
  3. 通过Socket对象调用getInputStream()方法得到字节输入流、完成数据的接收。
  4. 释放资源:关闭socket管道
ServerSocket serverSocket=new ServerSocket(6666);            
            Socket socket=serverSocket.accept();           
            InputStream is=socket.getInputStream();
            BufferedReader br=new BufferedReader(new InputStreamReader(is));
            String msg;
            while((msg=br.readLine())!=null){
                System.out.println(socket.getRemoteSocketAddress()+" "+msg);
            }

先运行服务端,然后打开客户发送端,成功发送。

TCP的B-S通信

要实现浏览器端的消息(浏览器显示服务端的内容),就要使得消息符合http响应数据协议格式:

System.out.println("***服务端***");
        try {
            //注册端口
            ServerSocket serverSocket=new ServerSocket(8080);
            while(true) {
                //接到一个socket管道
                Socket socket = serverSocket.accept();
                System.out.println(socket.getRemoteSocketAddress()+"访问了~");
                //新线程处理socket连接消息
                new serverReaderThread(socket).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
//处理进来的socket管道消息读取
public class serverReaderThread extends Thread {
    private Socket socket;
    public serverReaderThread(Socket socket){
        this.socket=socket;
    }
    @Override
    public void run() {
        try {
            PrintStream ps=new PrintStream(socket.getOutputStream());
            //HTTP
            ps.println("HTTP/1.1 200 OK");
            ps.println("Content-Type:text/html;charset=UTF-8");
            ps.println();
            ps.println("<span>hello </span>");
            ps.close();
        }catch (Exception e){
            System.out.println(socket.getRemoteSocketAddress()+"下线了~");
//            e.printStackTrace();
        }
    }
}

运行服务端后浏览器端就可以访问了。

相关文章
|
21天前
|
网络协议 算法 网络性能优化
|
22天前
|
Java 调度
[Java]线程生命周期与线程通信
本文详细探讨了线程生命周期与线程通信。文章首先分析了线程的五个基本状态及其转换过程,结合JDK1.8版本的特点进行了深入讲解。接着,通过多个实例介绍了线程通信的几种实现方式,包括使用`volatile`关键字、`Object`类的`wait()`和`notify()`方法、`CountDownLatch`、`ReentrantLock`结合`Condition`以及`LockSupport`等工具。全文旨在帮助读者理解线程管理的核心概念和技术细节。
35 1
[Java]线程生命周期与线程通信
|
8天前
|
Java
JAVA多线程通信:为何wait()与notify()如此重要?
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是实现线程间通信的核心机制。它们通过基于锁的方式,使线程在条件不满足时进入休眠状态,并在条件满足时被唤醒,从而确保数据一致性和同步。相比其他通信方式,如忙等待,这些方法更高效灵活。 示例代码展示了如何在生产者-消费者模型中使用这些方法实现线程间的协调和同步。
22 3
|
9天前
|
网络协议 SEO
TCP连接管理与UDP协议IP协议与ethernet协议
TCP、UDP、IP和Ethernet协议是网络通信的基石,各自负责不同的功能和层次。TCP通过三次握手和四次挥手实现可靠的连接管理,适用于需要数据完整性的场景;UDP提供不可靠的传输服务,适用于低延迟要求的实时通信;IP协议负责数据包的寻址和路由,是网络层的重要协议;Ethernet协议定义了局域网的数据帧传输方式,广泛应用于局域网设备之间的通信。理解这些协议的工作原理和应用场景,有助于设计和维护高效可靠的网络系统。
20 4
|
15天前
|
缓存 负载均衡 网络协议
面试:TCP、UDP如何解决丢包问题
TCP、UDP如何解决丢包问题。TCP:基于数据块传输/数据分片、对失序数据包重新排序以及去重、流量控制(滑动窗口)、拥塞控制、自主重传ARQ;UDP:程序执行后马上开始监听、控制报文大小、每个分割块的长度小于MTU
|
1月前
|
网络协议 前端开发 物联网
TCP和UDP区别?
本文首发于微信公众号“前端徐徐”,详细介绍了TCP和UDP两种传输层协议的核心概念、连接性和握手过程、数据传输和可靠性、延迟和效率、应用场景及头部开销。TCP面向连接、可靠、有序,适用于网页浏览、文件传输等;UDP无连接、低延迟、高效,适用于实时音视频传输、在线游戏等。
44 1
TCP和UDP区别?
|
1月前
|
存储 消息中间件 安全
JUC组件实战:实现RRPC(Java与硬件通过MQTT的同步通信)
【10月更文挑战第9天】本文介绍了如何利用JUC组件实现Java服务与硬件通过MQTT的同步通信(RRPC)。通过模拟MQTT通信流程,使用`LinkedBlockingQueue`作为消息队列,详细讲解了消息发送、接收及响应的同步处理机制,包括任务超时处理和内存泄漏的预防措施。文中还提供了具体的类设计和方法实现,帮助理解同步通信的内部工作原理。
JUC组件实战:实现RRPC(Java与硬件通过MQTT的同步通信)
|
23天前
|
Web App开发 缓存 网络协议
不为人知的网络编程(十八):UDP比TCP高效?还真不一定!
熟悉网络编程的(尤其搞实时音视频聊天技术的)同学们都有个约定俗成的主观论调,一提起UDP和TCP,马上想到的是UDP没有TCP可靠,但UDP肯定比TCP高效。说到UDP比TCP高效,理由是什么呢?事实真是这样吗?跟着本文咱们一探究竟!
49 10
|
23天前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
15 1
|
23天前
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
33 1