Java socket 封装了传输层的实现细节,开发人员可以基于 socket 实现应用层。本文介绍了 Java socket 简单用法。
传输层包含了两种协议,分别是 TCP (Transmission Control Protocol,传输控制协议) 和 UDP (User Datagram Protocol,用户数据报协议)。
TCP 是一种面向连接,可靠的流协议。通信双方在“发送-接收”数据之前需要先建立 TCP 连接,然后通过互相发送二进制数据流来进行通信。所谓连接,指的是各种设备、线路,或网络中进行通信的应用程序为了相互传递消息而建立的专有、虚拟的通信线路。连接一旦建立,进行通信的应用程序只使用该虚拟的通信线路发送和接收数据。TCP 还需要处理端到端之间的流量控制。
UDP 是一种无连接的,不可靠的数据报协议。发送方不需要与接收方建立连接,通信双方通过发送一个个独立的数据报来进行通讯。
TCP 通过序列号、确认应答、数据校验等机制确保了传输的可靠性,适用于需要可靠数据传输的场景,应用层协议 HTTP,FTP 基于 TCP。UDP 没有复杂的控制机制,不纠错,不重发,不保证数据的准确性,不确保数据到达目的地;不过 UDP 传送等量数据花费更小的流量,适用于对时延要求高但对准确性要求不高的场景,如视频、音频通讯。
Java 中有 3 种套接字类,java.net.Socket 和 java.net.ServerSocket 基于 TCP,java.net.DatagramSocket 基于 UDP。
TCP 是面向连接的,所以在进行通讯之前发送端(客户端)需要先连接到接收端(服务端)。客户端通过 new Socket("localhost", 9090) 来创建一个连接到服务端的套接字,这个套接字连接到主机 localhost 的 9090 端口。
ServerSocket 实现服务端套接字,通过 new ServerSocket(9090) 来创建一个监听端口为 9090 实例;ServerSocket.accept() 方法会阻塞等待客户端的连接,一旦有连接过来,会返回一个服务端的 Socket 实例。连接建立完成,客户端 Socket 实例和服务端 Socket 实例就可以面向输入输出流发送数据了。
客户端程序接收控制台输入的内容,客户端控制台每输入一行,就往服务端发送,服务端接收到消息之后,将消息打印到控制台。
客户端输入 "Bye" 时,客户端断开与服务端的连接,客户端程序退出,服务端程序继续等待连接。
客户端控制台输入输出:
$ java Server.java Bind Port 9090 New client connected. Received Message --> Are you OK!
服务端控制台输出:
$ java Client.java Are you OK! Send Msg --> Are you OK! Bye $
import java.net.*; import java.io.*; class Server { public static void main(String[] args) { // ServerSocket 实现了 AutoCloseable 接口,所以支持 try-with-resource 语句 // 创建一个 ServerSocket,监听 9090 端口 try(ServerSocket serv = new ServerSocket(9090)){ System.out.printf("Bind Port %d\n", serv.getLocalPort()); Socket socket = null; while(true){ // 接收连接,如果没有连接,accept() 方法会阻塞 socket = serv.accept(); // 获取输入流,并使用 BufferedInputStream 和 InputStreamReader 装饰,方便以字符流的形式处理,方便一行行读取内容 try(BufferedReader in = new BufferedReader( new InputStreamReader(socket.getInputStream()) )){ String msg = null; char[] cbuf = new char[1024]; int len = 0; while( (len = in.read(cbuf, 0, 1024)) != -1 ){ // 循环读取输入流中的内容 msg = new String(cbuf, 0, len); if("Bye".equals(msg)) { // 如果检测到 "Bye" ,则跳出循环,不再读取输入流中内容。 break; } System.out.printf("Received Message --> %s \n", msg); } }catch (IOException e){ e.printStackTrace(); } } }catch (IOException e){ e.printStackTrace(); } } } 2.3 客户端程序代码 import java.net.*; import java.io.*; import java.util.*; class Client{ public static void main(String[] args){ try(Socket socket = new Socket("localhost", 9090)){ BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); Scanner scanner = new Scanner(System.in); scanner.useDelimiter("\r\n"); String msg = null; while( !(msg = scanner.next()).equals("Bye") ){ System.out.printf("Send Msg --> %s \n", msg); out.write(msg); out.flush(); // 立即发送,否则需要积累到一定大小才一次性发送 } }catch (IOException e){ e.printStackTrace(); } } }
UDP 不需要连接,客户端与服务端通过发送数据报来完成通信。Java 中使用 java.net.DatagramSocket 来表示 UDP 客户端或服务端的套接字,使用 java.net.DatagramPacket 来表示 UDP 的数据报。客户端和服务端可以直接向对方发送数据报,不需要进行连接。
下面代码基于 UDP 实现了与上面程序同样的功能。不过消息可能会出错,某些消息可能也不能到达服务端。
import java.net.*; import java.io.*; class Server { public static void main(String[] args){ // 创建一个 DatagramPacket 实例,用来接收客户端发送过来的 UDP 数据报,这个实例可以重复利用。 byte[] buf = new byte[8192]; // 缓存区 int len = buf.length; // 要利用的缓存区的大小 DatagramPacket pac = new DatagramPacket(buf, len); // 创建服务端的套接字,需要指定绑定的端口号 try(DatagramSocket serv = new DatagramSocket(9191)){ while(true){ serv.receive(pac); // 接收数据报。如果没有数据报发送过来,会阻塞 System.out.println("Message --> " + new String(pac.getData(), 0, pac.getLength())); } }catch (IOException e){ e.printStackTrace(); } } }
import java.io.*; import java.net.*; import java.util.*; class Client { public static void main(String[] args){ // 创建一个客户端的 UDP 套接字,不需要指定任何信息 try(DatagramSocket client = new DatagramSocket()){ // 创建一个数据报实例,数据和长度在发送之前都会重新设置,所以这里直接置为 0 即可。 // 由于是发送端,所以需要设置服务端的地址和端口 DatagramPacket pac = new DatagramPacket(new byte[0], 0, InetAddress.getByName("localhost"), 9191); // 扫描控制台输入 Scanner scanner = new Scanner(System.in); scanner.useDelimiter("\r\n"); String msg = null; while( !(msg = scanner.next()).equals("Bye") ){ // 设置要发送的数据 pac.setData(msg.getBytes()); // 发送数据报 client.send(pac); System.out.println("Sent Message --> " + msg); } }catch (IOException e){ e.printStackTrace(); } } }
需要注意的是,UDP 是面向无连接的,但 DatagramSocket 的 API 中提供了带有 connect 字样的方法,这里的 connect 并非 TCP 中连接的意思。而是指定了当前的 UDP 套接字只能够向指定的主机和端口发送数据报。
以上就是Java 实现简单Socket 通信的示例的详细内容,更多关于Java 实现Socket 通信的资料请关注小牛知识库其它相关文章!
本文向大家介绍Java实现简单的socket通信教程,包括了Java实现简单的socket通信教程的使用技巧和注意事项,需要的朋友参考一下 今天学习了一下java如何实现socket通信,感觉难点反而是在io上,因为java对socket封装已经很完善了。 今天代码花了整个晚上调试,主要原因是io的flush问题和命令行下如何运行具有package的类,不过最后问题基本都解决了,把代码贴出来供大家
本文向大家介绍Python socket实现的简单通信功能示例,包括了Python socket实现的简单通信功能示例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Python socket实现的简单通信功能。分享给大家供大家参考,具体如下: 套接字(socket)是计算机网络数据结构,在任何类型的通信开始之前,网络应用程序必须创建套接字,可以将其比作电话的插孔,没有它将无法进行通信 常
本文向大家介绍python实现简单socket通信的方法,包括了python实现简单socket通信的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了python实现简单socket通信的方法。分享给大家供大家参考,具体如下: 刚刚开始接触python,实现了一个helloworld程序---关于udp协议的socket通信demo。 首先服务端这边的实现如下: 其中,host置为空,
本文向大家介绍基于Java语言实现Socket通信的实例,包括了基于Java语言实现Socket通信的实例的使用技巧和注意事项,需要的朋友参考一下 基于Java语言实现Socket通信 由于近日项目需求,需要在服务器中增加Socket通信的功能,接收硬件设备发送的心跳包和相关数据,因此又重新对Java的网络编程进行了复习,根据项目的实际情况做了简化的编程,实现了简单的通信过程。 1. Socket
本文向大家介绍python实现简单的socket server实例,包括了python实现简单的socket server实例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了python实现简单的socket server的方法。分享给大家供大家参考。具体如下: 希望本文所述对大家的Python程序设计有所帮助。
本文向大家介绍python3利用Socket实现通信的方法示例,包括了python3利用Socket实现通信的方法示例的使用技巧和注意事项,需要的朋友参考一下 参考于: python cs架构实现简单文件传输 原文中程序运行有误,在此做修改与解释,如下: 功能说明: 共2个py文件分别为server和client端,采用socket进行通信。提供两种功能:“dir“ 命令用于显示服务器端可下载文件