Java Sockets详解—官方原版

这篇具有很好参考价值的文章主要介绍了Java Sockets详解—官方原版。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、Socket概念

通常情况下,服务器运行在特定的计算机上,并且具有绑定到特定端口号的Socket。服务器只是等待,监听Socket,等待客户端发出连接请求。
在客户端:客户端知道服务器正在运行的机器的主机名以及服务器正在侦听的端口号。要发出连接请求,客户端会尝试在服务器的计算机和端口上与服务器会合。客户端还需要向服务器标识自己,以便绑定到将在连接过程中使用的本地端口号。这通常是由系统分配的。

java socket,java基础,java

如果一切顺利,服务器将接受连接。接受后,服务器将获得一个绑定到同一本地端口的新Socket,并将其远程端点设置为客户端的地址和端口。它需要一个新的Socket,这样它就可以继续侦听原始套接字的连接请求,同时满足连接的客户端的需求。

java socket,java基础,java

 在客户端,如果连接被接受,则成功创建了一个Socket,客户端可以使用该Socket与服务器通信。
客户端和服务器现在可以通过向Socket写入或从Socket读取数据来进行通信。

端点是IP地址和端口号的组合。每个TCP连接都可以由其两个端点唯一标识。这样,您就可以在主机和服务器之间建立多个连接。
java平台中的java.net包提供了一个类Socket,它实现了java程序和网络上另一个程序之间双向连接的一端。Socket类位于依赖于平台的实现之上,可以向Java程序隐藏任何特定系统的详细信息。通过使用java.net.Socket类而不是依赖于本机代码,java程序可以以独立于平台的方式通过网络进行通信。
此外,java.net还包括ServerSocket类,它实现了一个套接字,服务器可以使用该套接字来侦听和接受与客户端的连接。本课程向您展示如何使用Socket和ServerSocket类。
如果您试图连接到Web,URL类和相关类(URLConnection、URLEncoder)可能比套接字类更合适。事实上,URL是到Web的一种相对高级的连接,并使用套接字作为底层实现的一部分。

二、读取和写入Socket

让我们看一个简单的例子,它说明了程序如何使用Socket类建立与服务器程序的连接,然后说明了客户端如何通过套接字向服务器发送数据和从服务器接收数据。
示例程序实现了一个客户端EchoClient,该客户端连接到echo服务器。echo服务器从其客户端接收数据并将其回显。示例EchoServer实现了一个回声服务器。(或者,客户端可以连接到任何支持回声协议的主机。)
EchoClient示例创建一个套接字,从而连接到echo服务器。它在标准输入流上读取用户的输入,然后通过将文本写入套接字将文本转发到echo服务器。服务器通过套接字将输入返回到客户端。客户端程序读取并显示从服务器传回的数据。
请注意,EchoClient示例既向其套接字写入数据,又从其套接字读取数据,从而向echo服务器发送数据,并从其接收数据。
让我们浏览一下这个程序,并调查其中有趣的部分。EchoClient示例中的try with resources语句中的以下语句至关重要。这些行在客户端和服务器之间建立套接字连接,并在套接字上打开PrintWriter和BufferedReader:

String hostName = args[0];
int portNumber = Integer.parseInt(args[1]);

try (
    Socket echoSocket = new Socket(hostName, portNumber);        // 1st statement
    PrintWriter out =                                            // 2nd statement
        new PrintWriter(echoSocket.getOutputStream(), true);
    BufferedReader in =                                          // 3rd statement 
        new BufferedReader(
            new InputStreamReader(echoSocket.getInputStream()));
    BufferedReader stdIn =                                       // 4th statement 
        new BufferedReader(
            new InputStreamReader(System.in))
)

try-with-resources语句中的第一条语句创建了一个新的Socket对象,并将其命名为echoSocket。这里使用的Socket构造函数需要计算机的名称和要连接的端口号。示例程序使用第一个命令行参数作为计算机名称(主机名),使用第二个命令行自变量作为端口号。在计算机上运行此程序时,请确保使用的主机名是要连接的计算机的完全限定IP名。例如,如果您的echo服务器正在计算机echoserver.example.com上运行,并且正在侦听端口号7,如果您想使用echoserver示例作为echo服务器,请首先从计算机echoseserver.example.com运行以下命令:

java EchoServer 7

之后,使用以下命令运行EchoClient示例:

java EchoClient echoserver.example.com 7

try-with-resources语句中的第二条语句获取套接字的输出流,并在其上打开一个名为out的PrintWriter。类似地,第三条语句获取套接字的输入流,并在其中打开一个名为的BufferedReader。该示例使用读取器和写入器,以便可以在套接字上写入Unicode字符。如果您还不熟悉Java平台的I/O类,您可能希望阅读Basic I/O。
程序的下一个有趣部分是while循环。循环每次从带有BufferedReader对象stdIn的标准输入流中读取一行,该对象是在try-with-resources语句的第四条语句中创建的。然后,循环通过将该行写入连接到套接字的PrintWriter,立即将该行发送到服务器:

String userInput;
while ((userInput = stdIn.readLine()) != null) {
    out.println(userInput);
    System.out.println("echo: " + in.readLine());
}

while循环中的最后一条语句从连接到套接字的BufferedReader中读取一行信息。readLine方法等待,直到服务器将信息回显给EchoClient。当readline返回时,EchoClient将信息打印到标准输出。
while循环一直持续到用户键入输入字符的末尾。也就是说,EchoClient示例读取用户的输入,将其发送到Echo服务器,从服务器获取响应并显示,直到输入结束。(您可以按Ctrl-C键键入输入字符的末尾。)while循环随后终止,Java运行时会自动关闭连接到套接字和标准输入流的读写器,并关闭与服务器的套接字连接。Java运行时会自动关闭这些资源,因为它们是在try-with-resources语句中创建的。Java运行时以与创建这些资源相反的顺序关闭这些资源。(这很好,因为连接到套接字的流应该在套接字本身关闭之前关闭。)
这个客户端程序简单明了,因为echo服务器实现了一个简单的协议。客户端将文本发送到服务器,服务器将其回显。当客户端程序与更复杂的服务器(如HTTP服务器)通信时,客户端程序也会更复杂。然而,基本原理与本程序中的基本原理基本相同:

  1. 打开Socket。
  2. 打开输入流并将输出流输出到套接字。
  3. 根据服务器的协议读取和写入流。
  4. 关闭流。
  5. 关闭Socket。

只有步骤 3 因客户端而异,具体取决于服务器。其他步骤基本保持不变。

三、写入服务端Socket

该示例由两个独立运行的Java程序组成:客户端程序和服务器程序。客户端程序由一个类KnockKnockClient实现,与上一节中的EchoClient示例非常相似。服务器程序由两个类实现:KnockKnockServer和KnockKnocksProtocol。KnockKnockServer类似于EchoServer,包含服务器程序的主要方法,并执行侦听端口、建立连接以及读取和写入套接字的工作。KnockKnockProtocol这门课讲笑话。它跟踪当前笑话和当前状态(发送的敲门声、发送的线索等),并根据当前状态返回笑话的各种文本片段。这个对象实现了协议——客户端和服务器已经同意使用的语言来进行通信。
以下部分详细介绍了客户端和服务器中的每个类,然后向您展示了如何运行它们。

Knock Knock服务器

本节将介绍实现KnockKnock服务器程序KnockKnockServer的代码。
服务器程序首先创建一个新的ServerSocket对象来侦听特定的端口(请参阅下面代码段中的粗体语句)。运行此服务器时,请选择一个尚未专用于其他服务的端口。例如,此命令启动服务器程序KnockKnockServer,使其在端口8888上侦听:

java KnockKnockServer 8888

服务器程序在try-with-resources语句中创建ServerSocket对象:

       int portNumber = Integer.parseInt(args[0]);
        try {
            ServerSocket serverSocket = new ServerSocket(portNumber);
            Socket clientSocket = serverSocket.accept();
            PrintWriter out =
                    new PrintWriter(clientSocket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(clientSocket.getInputStream()));
        } catch (Exception e) {
            
        }

ServerSocket是一个java.net类,它提供了客户端/服务器套接字连接的服务器端的独立于系统的实现。如果ServerSocket的构造函数无法侦听指定的端口(例如,该端口已在使用中),则会引发异常。在这种情况下,KnockKnockServer别无选择,只能退出。
如果服务器成功绑定到其端口,则ServerSocket对象将成功创建,服务器将继续执行下一步,接受来自客户端的连接(try-with-resources语句中的下一条语句):

clientSocket = serverSocket.accept();

accept方法等待,直到客户端启动并请求在该服务器的主机和端口上建立连接。(假设您在名为KnockKnockServer.example.com的计算机上运行了服务器程序KnockKnockServer。)在本例中,服务器在第一个命令行参数指定的端口号上运行。当请求并成功建立连接时,accept方法返回一个新的Socket对象,该对象绑定到同一本地端口,并将其远程地址和远程端口设置为客户端的远程地址和端口。服务器可以通过这个新的套接字与客户端通信,并继续侦听原始ServerSocket上的客户端连接请求。这个特定版本的程序不会侦听更多的客户端连接要求。但是,在“支持多个客户端”中提供了该程序的修改版本。
服务器与客户端成功建立连接后,将使用以下代码与客户端进行通信:

try {
            // ...
            PrintWriter out =
                    new PrintWriter(clientSocket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(clientSocket.getInputStream()));

            String inputLine, outputLine;

            // Initiate conversation with client
            KnockKnockProtocol kkp = new KnockKnockProtocol();
            outputLine = kkp.processInput(null);
            out.println(outputLine);

            while ((inputLine = in.readLine()) != null) {
                outputLine = kkp.processInput(inputLine);
                out.println(outputLine);
                if (outputLine.equals("Bye."))
                    break;
            }
        }
        catch (Exception e)
        {
            
        }

此代码执行以下操作:

  1. 获取Socket的输入和输出流,并打开它们上的读写器。
  2. 通过写入Socket(以粗体显示)来启动与客户端的通信。
  3. 通过读取和写入套接字与客户端通信(while循环)。

步骤1已经很熟悉了。步骤2以粗体显示,值得一些评论。上面代码段中的粗体语句启动了与客户的对话。该代码创建了一个KnockKnockProtocol对象,该对象跟踪当前笑话、笑话中的当前状态等。
创建KnockKnockProtocol后,代码调用KnockKnocksProtocol的processInput方法来获取服务器发送给客户端的第一条消息。对于这个例子,服务器说的第一句话是“Knock!Knock!”接下来,服务器将信息写入连接到客户端套接字的PrintWriter,从而将消息发送到客户端。
步骤3在while循环中进行编码。只要客户端和服务器之间还有话要说,服务器就会从套接字中读取和写入,在客户端和服务器间来回发送消息。
服务器用“Knock!Knock!”启动对话,因此之后服务器必须等待客户端说“谁在那里?”因此,while循环迭代输入流中的读取。readLine方法等待,直到客户端通过向其输出流(服务器的输入流)写入内容来做出响应。当客户端响应时,服务器将客户端的响应传递给KnockKnockProtocol对象,并向KnockKnock Protocol对象请求合适的答复。服务器使用对println的调用,通过连接到套接字的输出流立即向客户端发送回复。如果服务器从KnockKnockServer对象生成的响应是“再见”,这表明客户端不想再开玩笑了,循环就退出了。
Java运行时会自动关闭输入和输出流、客户端套接字和服务器套接字,因为它们是在try-with-resources语句中创建的。

Knock Knock客户端

KnockKnockClient类实现了与KnockKnockServer对话的客户端程序。KnockKnockClient基于上一节“从套接字读取和写入套接字”中的EchoClient程序,您应该对此有些熟悉。但无论如何,我们都会查看该程序,并在服务器中发生的情况下查看客户端中发生的事情。
启动客户端程序时,服务器应该已经在运行并侦听端口,等待客户端请求连接。因此,客户端程序要做的第一件事是打开一个套接字,该套接字连接到在指定主机名和端口上运行的服务器:

        String hostName = args[0];
        int portNumber = Integer.parseInt(args[1]);

        try {
            Socket kkSocket = new Socket(hostName, portNumber);
            PrintWriter out = new PrintWriter(kkSocket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(kkSocket.getInputStream()));
        }catch (Exception e)
        {
            
        }

在创建套接字时,KnockKnockClient示例使用第一个命令行参数的主机名,即网络上运行服务器程序KnockKnockServer的计算机的名称。
KnockKnockClient示例在创建套接字时使用第二个命令行参数作为端口号。这是一个远程端口号,即服务器计算机上的端口号,是KnockKnockServer正在侦听的端口。例如,以下命令运行KnockKnockClient示例,knockknockserver.example.com是运行服务器程序knockknockserver的计算机的名称,8888是远程端口号:

java KnockKnockClient knockknockserver.example.com 8888

客户端的套接字绑定到任何可用的本地端口,即客户端计算机上的端口。请记住,服务器也会得到一个新的套接字。如果使用上一个示例中的命令行参数运行KnockKnockClient示例,则此套接字将绑定到运行KnockKnockClient示例的计算机上的本地端口号8888。服务器的套接字和客户端的套接字已连接。
接下来是while循环,它实现了客户端和服务器之间的通信。服务器先发言,所以客户端必须先监听。客户端通过读取连接到套接字的输入流来完成这一操作。如果服务器真的说话了,它会说“再见”,客户端就会退出循环。否则,客户端将文本显示到标准输出,然后读取用户的响应,用户在标准输入中键入。用户键入回车后,客户端通过连接到套接字的输出流将文本发送到服务器。

while ((fromServer = in.readLine()) != null) {
    System.out.println("Server: " + fromServer);
    if (fromServer.equals("Bye."))
        break;

    fromUser = stdIn.readLine();
    if (fromUser != null) {
        System.out.println("Client: " + fromUser);
        out.println(fromUser);
    }
}

当服务器问客户是否想再听一个笑话,客户说不想,服务器说“再见”时,通信结束
客户端会自动关闭其输入和输出流以及套接字,因为它们是在try-with-resources语句中创建的。

运行程序

必须先启动服务器程序。为此,请使用 Java 解释器运行服务器程序,就像运行任何其他 Java 应用程序一样。将服务器程序侦听的端口号指定为命令行参数:

java KnockKnockServer 8888

接下来,运行客户端程序。请注意,您可以在网络上的任何计算机上运行客户端;它不必与服务器在同一台计算机上运行。将运行KnockKnockServer服务器程序的计算机的主机名和端口号指定为命令行参数:

java KnockKnockClient knockknockserver.example.com 8888

如果速度太快,则可能会在服务器有机会初始化自身并开始侦听端口之前启动客户端。如果发生这种情况,您将看到来自客户端的堆栈跟踪。如果发生这种情况,只需重新启动客户端即可。

支持多个客户端

为了使KnockKnockServer示例保持简单,我们将其设计为侦听和处理单个连接请求。但是,多个客户端请求可以进入同一端口,从而进入同一ServerSocket。客户端连接请求在端口排队,因此服务器必须按顺序接受连接。然而,服务器可以通过使用线程同时为它们提供服务,每个客户端连接一个线程。
这种服务器中的基本逻辑流程是:

while (true) {
    accept a connection;
    create a thread to deal with the client;
}

线程根据需要读取和写入客户端连接。
java官网https://docs.oracle.com/javase/tutorial/networking/sockets/index.html

大家好,我是Doker品牌的Sinbad,欢迎点赞和评论,您的鼓励是我们持续更新的动力!欢迎加微信进入技术群聊! 文章来源地址https://www.toymoban.com/news/detail-775109.html

到了这里,关于Java Sockets详解—官方原版的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java Socket 编程详解

    Java Socket 编程是指使用 Java 语言进行网络通信的过程,包括建立连接、传输数据和关闭连接等操作。Java 提供了 java.net.Socket 和 java.net.ServerSocket 两个类来支持 Socket 编程。 1.1 Socket 概述 Socket 指的是“插座”,是应用层与传输层之间的桥梁,用于在网络上进行双向通信。在 S

    2024年02月03日
    浏览(34)
  • 详解JAVA Socket

    目录 1.概述 2.使用 3.使用场景 3.1.web server中的网络通信 3.2.长连接 3.3.性能问题 什么是网络通信: 就像打电话一样,两点间要通信,两点间就必须有连接,为了实现任意两个节点之间的通信,我们就必须采取手段将所有节点连接起来,形成了一个巨大的拓扑结构,这就是计算

    2024年02月12日
    浏览(40)
  • Java 网络编程 —— Socket 详解

    在【客户端/服务端】的通信模式中,客户端需要主动构造与服务器连接的 Socket,构造方法有以下几种重载形式: 除了第一个不带参数的构造方法,其他构造方法都会试图建立与服务器的连接,一旦连接成功,就返回 Socket 对象,否则抛出异常 1. 设定等待建立连接的超时时间

    2024年02月01日
    浏览(35)
  • 【MySQL】如何使用Unix Sockets 协议连接MySQL数据库

    MySQL入门02:关于MySQL连接的ABC 【MySQL】如何使用Named Pipe协议(Windows)连接MySQL数据库 【MySQL】如何使用Shared-memory协议(Windows)连接MySQL数据库 【MySQL】如何使用Unix Sockets 协议连接MySQL数据库 【免责声明】文章仅供学习交流,观点代表个人,与任何公司无关。 编辑|SQL和数据库技术

    2024年02月11日
    浏览(46)
  • Linux下C语言使用 netlink sockets与内核模块通信

    Netlink套接字是用以实现用户进程与内核进程通信的一种特殊的进程间通信(IPC) ,也是网络应用程序与内核通信的最常用的接口。在Linux标准内核中,系统默认集成了很多netlink实例,比如日志上报、路由系统等,netlink消息是双向的,应用层可以发送消息到内核,同时内核也可以

    2024年02月07日
    浏览(55)
  • Unity3D 网络游戏框架(二、同步Socket) 参考连接:Socket 类 (System.Net.Sockets) | Microsoft Learn

    1、Socket.Connect() 2、Socket.Send() 3、Socket.Receive() 在了解完Socket通讯流程图和相关API之后我们来开发客户端代码:  在Unity中添加 两个Button、一个InputField和有Text ,Connect 方法 绑定连接的按钮, Send 方法绑定发送按钮。 Connect :客户端点击连接后会和服务端进行连接,这里面127

    2024年02月16日
    浏览(49)
  • Flask-Sockets和Flask-Login联合实现websocket的登录认证功能

    flask_login 提供了一个方便的方式来管理用户会话。当你在 Flask 的 HTTP 视图中使用它时,你可以简单地使用 @login_required 装饰器来确保用户已登录。 但是, flask_sockets 并没有直接与 flask_login 集成。如果你想在建立 WebSocket 连接时检查用户是否已登录,你需要采取一些额外的步骤

    2024年02月11日
    浏览(42)
  • Java实现socket通信详解(UDP/TCP)c/s模式

    在实现具体代码前,我们先来简单了解下TCP/UDP协议 TCP在OSI模型中位于传输层在网络层之上,故在端到端传输的基础上将数据以端口号等标识实现进程/终端设备应用的区分, 将数据精准的传达。 TCP全称为传输控制协议具有以下特点: 面向有连接的服务可靠的数据传输,即在

    2023年04月08日
    浏览(36)
  • SSE(Server-Sent Events,服务器推送事件)和sockets(套接字)通信区别

    SSE(Server-Sent Events,服务器推送事件)和sockets(套接字)都是用于实现实时通信的技术,但它们具有不同的特点和应用场景。 SSE 的优点: 简单易用:SSE 是基于HTTP协议的一种实时通信技术,使用简单,只需要在客户端通过EventSource对象监听服务器推送的事件即可。 可靠性:

    2024年02月15日
    浏览(51)
  • Office 365 官方原版镜像下载

    中文说明:专业增强版-简体中文版 文件名称:O365ProPlusRetail.img 下载地址:https://officecdn.microsoft.com/db/492350F6-3A01-4F97-B9C0-C7C6DDF67D60/media/zh-CN/O365ProPlusRetail.img 中文说明:专业增强版-繁体中文版 文件名称:O365ProPlusRetail.img 下载地址:https://officecdn.microsoft.com/db/492350F6-3A01-4F97-B9

    2024年02月12日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包