Java TCP和UDP简介
来源:互联网 发布:网络歌手小右个人 编辑:程序博客网 时间:2024/05/18 17:42
UDP
用户数据报协议,无需建立连接就可以向目标地址和目标端口发送数据报,没有流量控制、拥塞控制、重传机制,这些需要依靠用户进程自己实现。应用领域有远程过程调用(RPC)、实时多媒体应用(语音视频)等。优点是效率高、占用资源少,缺点是不可靠。
UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。这也就是说,应用层交给UDP多长的报文,UDP就照样发送,一次发送一个报文。报文最大长度有限制,否则会导致IP层分片,最大值最好小于548字节。
单播
服务端,ip地址是192.168.1.105
import java.net.DatagramPacket;import java.net.DatagramSocket;/** * Created by ICE on 2017-05-04 */public class UDPServer { public static void main(String[] args) throws Exception { System.out.println("启动UDP服务端"); // 构造DatagramSocket实例,随机指定本地端口 try (DatagramSocket datagramSocket = new DatagramSocket()) { //设置超时时间为10秒 datagramSocket.setSoTimeout(10000); while (true) { // 构造DatagramPacket实例,用来接收最大长度为512字节的数据包 byte[] data = new byte[512]; DatagramPacket receivePacket = new DatagramPacket(data, 512); // 接收报文,此方法在接收到数据报前一直阻塞 datagramSocket.receive(receivePacket); System.out.println("客户端地址:" + receivePacket.getAddress().getHostAddress()); System.out.println("客户端端口:" + receivePacket.getPort()); System.out.println("接收到的数据长度:" + receivePacket.getLength()); System.out.println("接收到的数据:" + new String(receivePacket.getData(), 0, receivePacket.getLength(), "UTF-8")); } } }}
客户端,ip地址是192.168.1.139
import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetSocketAddress;/** * Created by ICE on 2017-05-06 */public class UDPClient { public static void main(String[] args) throws Exception { { // 构造DatagramSocket实例,指定本地端口6666。 try (DatagramSocket datagramSocket = new DatagramSocket(6666)) { for (int i = 0; i < 5; i++) { String data = "当前循环:" + i; // 构造数据报包,用来将data发送到指定主机上的指定端口号。 DatagramPacket sendPacket = new DatagramPacket(data.getBytes("UTF-8"), data.getBytes("UTF-8").length, new InetSocketAddress("192.168.1.105", 6666)); //发送报文 datagramSocket.send(sendPacket); } } } }}
服务端输出
启动UDP服务端客户端地址:192.168.1.139客户端端口:58251接收到的数据长度:16接收到的数据:当前循环:0客户端地址:192.168.1.139客户端端口:58251接收到的数据长度:16接收到的数据:当前循环:1客户端地址:192.168.1.139客户端端口:58251接收到的数据长度:16接收到的数据:当前循环:2客户端地址:192.168.1.139客户端端口:58251接收到的数据长度:16接收到的数据:当前循环:3客户端地址:192.168.1.139客户端端口:58251接收到的数据长度:16接收到的数据:当前循环:4Exception in thread "main" java.net.SocketTimeoutException: Receive timed outat java.net.DualStackPlainDatagramSocketImpl.socketReceiveOrPeekData(Native Method)at java.net.DualStackPlainDatagramSocketImpl.receive0(DualStackPlainDatagramSocketImpl.java:120)at java.net.AbstractPlainDatagramSocketImpl.receive(AbstractPlainDatagramSocketImpl.java:144)at java.net.DatagramSocket.receive(DatagramSocket.java:812)at UDPServer.main(UDPServer.java:19)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:497)at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
组播
如果主机是多网卡,那么此时就需要注意了,一定要设置用哪个网卡发送和接受数据,因为组播是无法跨网段的,否则会导致数据接收不到。
发送端,ip地址是192.168.22.1。MulticastSocket继承于DatagramSocket,因此可以发送也可以接收数据包。MulticastSocket绑定的端口是接收和发送数据的,如果数据包目的端口和此端口一致,则这个程序就能接收到数据包。setNetworkInterface方法是用来绑定网卡的。joinGroup告诉主机该程序要加入到哪个组播组,leaveGroup则是退出组播组。其他用法和DatagramSocket基本一致。
import java.net.DatagramPacket;import java.net.InetAddress;import java.net.MulticastSocket;import java.net.NetworkInterface;public class MultiCastNode1 { public static void main(String[] args) throws Exception { InetAddress inetAddress = InetAddress.getByName("228.0.0.8"); MulticastSocket multicastSocket = new MulticastSocket(); multicastSocket.setNetworkInterface(NetworkInterface.getByInetAddress(InetAddress.getByName("192.168.22.1"))); multicastSocket.joinGroup(inetAddress); while (true) { String message = "时间戳:" + System.currentTimeMillis(); byte[] bytes = message.getBytes("UTF-8"); DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, inetAddress, 8888); multicastSocket.send(datagramPacket); } }}
接收端,ip地址是192.168.22.133
import java.net.DatagramPacket;import java.net.InetAddress;import java.net.MulticastSocket;import java.net.NetworkInterface;public class MultiCastNode2 { public static void main(String[] args) throws Exception { InetAddress inetAddress = InetAddress.getByName("228.0.0.8"); MulticastSocket multicastSocket = new MulticastSocket(8888); multicastSocket.setNetworkInterface(NetworkInterface.getByInetAddress(InetAddress.getByName("192.168.22.133"))); multicastSocket.joinGroup(inetAddress); int count = 0; while (true) { if (count == 5) { multicastSocket.leaveGroup(inetAddress); return; } // 构造DatagramPacket实例,用来接收最大长度为512字节的数据包 byte[] data = new byte[512]; DatagramPacket receivePacket = new DatagramPacket(data, 512); // 接收报文,此方法在接收到数据报前一直阻塞 multicastSocket.receive(receivePacket); System.out.println("客户端地址:" + receivePacket.getAddress().getHostAddress()); System.out.println("客户端端口:" + receivePacket.getPort()); System.out.println("接收到的数据长度:" + receivePacket.getLength()); System.out.println("接收到的数据:" + new String(receivePacket.getData(), 0, receivePacket.getLength(), "UTF-8")); count++; } }}
接收端输出
客户端地址:192.168.22.1
客户端端口:50958
接收到的数据长度:25
接收到的数据:时间戳:1509421450872
客户端地址:192.168.22.1
客户端端口:50958
接收到的数据长度:25
接收到的数据:时间戳:1509421450872
客户端地址:192.168.22.1
客户端端口:50958
接收到的数据长度:25
接收到的数据:时间戳:1509421450872
客户端地址:192.168.22.1
客户端端口:50958
接收到的数据长度:25
接收到的数据:时间戳:1509421450872
客户端地址:192.168.22.1
客户端端口:50958
接收到的数据长度:25
接收到的数据:时间戳:1509421450872
TCP
import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.net.InetSocketAddress;import java.net.ServerSocket;import java.net.Socket;import java.util.Arrays;/** * Created by ICE on 2017-05-06 */public class TCPServer { public static void main(String[] args) throws Exception { System.out.println("启动TCP服务端"); //构造ServerSocket实例,指定监听的本地端口 try (ServerSocket serverSocket = new ServerSocket(6666)) { //设置超时时间为10秒 serverSocket.setSoTimeout(10000); while (true) { //侦听并接收到此套接字的连接,此方法在连接传入之前一直阻塞。 Socket socket = serverSocket.accept(); TCPServerHandleThread tcpServerHandleThread = new TCPServerHandleThread(socket); Thread thread = new Thread(tcpServerHandleThread); thread.start(); } } }}/** * 为每个连接进来的请求单独起一个处理线程 */class TCPServerHandleThread implements Runnable { private Socket socket; public TCPServerHandleThread(Socket socket) { this.socket = socket; } @Override public void run() { try { try (BufferedInputStream inputStream = new BufferedInputStream(socket.getInputStream()); BufferedOutputStream outputStream = new BufferedOutputStream(socket.getOutputStream())) { //每次读取的最大字节数,为了演示特地写小一点 byte[] bytes = new byte[8]; //每次读取的有效字节数 int count; //结果数组 byte[] result = new byte[0]; while ((count = inputStream.read(bytes)) != -1) { //本次读取的有效字节数组 byte[] temp1 = Arrays.copyOfRange(bytes, 0, count); //复制结果数组到新数组,新数组长度为结果数组的长度加上本次读取的有效字节数,用0填充 byte[] temp2 = Arrays.copyOf(result, result.length + count); //将本次读取的有效字节数组放到新数组里 System.arraycopy(temp1, 0, temp2, result.length, count); result = temp2; } InetSocketAddress inetSocketAddress = (InetSocketAddress) socket.getRemoteSocketAddress(); System.out.println("客户端的ip和端口:" + inetSocketAddress.getAddress() + " " + inetSocketAddress.getPort()); InetSocketAddress inetSocketAddressL = (InetSocketAddress) socket.getLocalSocketAddress(); System.out.println("本地绑定的ip和端口:" + inetSocketAddressL.getAddress() + " " + inetSocketAddressL.getPort()); System.out.println("接收到的数据长度:" + result.length); System.out.println("接收到的数据:" + new String(result, "UTF-8")); //关闭此socket输入流 socket.shutdownInput(); outputStream.write("接收完毕".getBytes("UTF-8")); outputStream.flush(); //关闭此socket输出流 socket.shutdownOutput(); } finally { socket.close(); } } catch (Exception e) { e.printStackTrace(); } }}
客户端,ip地址是192.168.1.139
import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.net.InetSocketAddress;import java.net.Socket;/** * * Created by ICE on 2017-05-06 */public class TCPClient { public static void main(String[] args) throws Exception { // 构造Socket实例 try (Socket socket = new Socket("192.168.1.105", 6666); BufferedInputStream inputStream = new BufferedInputStream(socket.getInputStream()); BufferedOutputStream outputStream = new BufferedOutputStream(socket.getOutputStream())) { InetSocketAddress inetSocketAddress = (InetSocketAddress) socket.getRemoteSocketAddress(); System.out.println("服务端的ip和端口:" + inetSocketAddress.getAddress() + " " + inetSocketAddress.getPort()); InetSocketAddress inetSocketAddressL = (InetSocketAddress) socket.getLocalSocketAddress(); System.out.println("本地绑定的ip和端口:" + inetSocketAddressL.getAddress() + " " + inetSocketAddressL.getPort()); outputStream.write("abcdefg测试数据1234567890".getBytes("UTF-8")); outputStream.flush(); //关闭此socket输出流 socket.shutdownOutput(); byte[] bytes = new byte[1024]; int count; if ((count = inputStream.read(bytes)) != -1) { System.out.println(new String(bytes, 0, count, "UTF-8")); } //关闭此socket输入流 socket.shutdownInput(); } }}
服务端输出
启动TCP服务端客户端的ip和端口:/192.168.1.139 37810本地绑定的ip和端口:/192.168.1.105 6666接收到的数据长度:29接收到的数据:abcdefg测试数据1234567890Exception in thread "main" java.net.SocketTimeoutException: Accept timed outat java.net.DualStackPlainSocketImpl.waitForNewConnection(Native Method)at java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:135)at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:404)at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:199)at java.net.ServerSocket.implAccept(ServerSocket.java:545)at java.net.ServerSocket.accept(ServerSocket.java:513)at TCPServer.main(TCPServer.java:20)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)at java.lang.reflect.Method.invoke(Method.java:497)at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
客户端输出
服务端的ip和端口:/192.168.1.105 6666本地绑定的ip和端口:/192.168.1.139 37810接收完毕
客户端还可以采用如下方式设置连接超时时间为10秒
Socket socket = new Socket();socket.connect(new InetSocketAddress("192.168.1.105", 6666), 10000);
- Java TCP和UDP简介
- TCP和UDP协议简介
- Socket、HTTP和TCP、UDP简介
- Socket、HTTP和TCP、UDP简介
- IP,端口,tcp和udp简介
- 【美乃滋酱学java】UDP和TCP
- java基础---UDP和TCP
- java中的UDP和TCP
- TCP/UDP简介
- TCP UDP简介
- (Java 基础知识)Java TCP和UDP
- Java 网络概述 和 TCP 和 UDP
- Java网络编程:TCP和UDP
- Java 使用 TCP 和 UDP 传输文件
- JAVA网络编程TCP和UDP
- java——TCP和UDP
- Java 网络编程之TCP和UDP
- Java之网络编程UDP和TCP
- Kaldi学习笔记(二)
- Hdu 3401 题解 单调队列优化DP
- oracle分析函数系列之rank,dense_rank,row_number:实现排名策略
- WIN7 双系统安装
- java静态内部类与普通内部类
- Java TCP和UDP简介
- 常用排序算法-冒泡排序
- ModuleNotFoundError: No module named 'Cookie'
- scala基础7 —— scala的静态类型(object)
- jQuery 3 DOM操作
- 手把手带你做一个超炫酷loading成功动画view Android自定义view
- 迭代器 Iterator
- matlab 文件路径问题
- Python 3基础教程14-在文件尾部更新内容