当前位置: 首页 > 面试题库 >

Java网络:在套接字中解释InputStream和OutputStream

田冥夜
2023-03-14
问题内容

我已经使用创建了服务器ServerSocket。之后,我使用创建了Client Socket,并连接到该服务器。

之后,我对InputStream和OutputStream进行了“一些处理”,它们是从Socket
Object中获取的。但是,我不太了解inputStream和outputStream。这是我的简单代码:

private Socket sock = null;
private InputStream sockInput = null;
private OutputStream sockOutput = null;

...
            String msg = "Hello World";
            byte[] buffer = null;

            try {
                sockOutput.write(msg.getBytes(), 0, test.length());
                sockOutput.write("Hello StackOverFlow".getBytes(), 0, test.length());
                buffer = new byte[test.length()];
                sockInput.read(buffer, 0, test.length());
                System.out.println(new String(buffer));
                sockInput.read(buffer, 0, test.length());
                System.out.println(new String(buffer));
            } catch (IOException e1) {
                e1.printStackTrace();
                }

结果将是:“ Hello World”和“ Hello StackOverFlow”。

这是服务器端代码:

private int serverPort = 0;
    private ServerSocket serverSock = null;

    public VerySimpleServer(int serverPort) {
        this.serverPort = serverPort;

        try {
            serverSock = new ServerSocket(this.serverPort);
        }
        catch (IOException e){
            e.printStackTrace(System.err);
        }
    }

    // All this method does is wait for some bytes from the
    // connection, read them, then write them back again, until the
    // socket is closed from the other side.
    public void handleConnection(InputStream sockInput, OutputStream sockOutput) {
        while(true) {
            byte[] buf=new byte[1024];
            int bytes_read = 0;
            try {
                // This call to read() will wait forever, until the
                // program on the other side either sends some data,
                // or closes the socket.
                bytes_read = sockInput.read(buf, 0, buf.length);

                // If the socket is closed, sockInput.read() will return -1.
                if(bytes_read < 0) {
                    System.err.println("Server: Tried to read from socket, read() returned < 0,  Closing socket.");
                    return;
                }
                System.err.println("Server: Received "+bytes_read
                                   +" bytes, sending them back to client, data="
                                   +(new String(buf, 0, bytes_read)));
                sockOutput.write(buf, 0, bytes_read);
                // This call to flush() is optional - we're saying go
                // ahead and send the data now instead of buffering
                // it.
                sockOutput.flush();
            }
            catch (Exception e){
                System.err.println("Exception reading from/writing to socket, e="+e);
                e.printStackTrace(System.err);
                return;
            }
        }

    }

    public void waitForConnections() {
        Socket sock = null;
        InputStream sockInput = null;
        OutputStream sockOutput = null;
        while (true) {
            try {
                // This method call, accept(), blocks and waits
                // (forever if necessary) until some other program
                // opens a socket connection to our server.  When some
                // other program opens a connection to our server,
                // accept() creates a new socket to represent that
                // connection and returns.
                sock = serverSock.accept();
                System.err.println("Server : Have accepted new socket.");

                // From this point on, no new socket connections can
                // be made to our server until we call accept() again.

                sockInput = sock.getInputStream();
                sockOutput = sock.getOutputStream();
            }
            catch (IOException e){
                e.printStackTrace(System.err);
            }

            // Do something with the socket - read bytes from the
            // socket and write them back to the socket until the
            // other side closes the connection.
            handleConnection(sockInput, sockOutput);

            // Now we close the socket.
            try {
                System.err.println("Closing socket.");
                sock.close();
            }
            catch (Exception e){
                System.err.println("Exception while closing socket.");
                e.printStackTrace(System.err);
            }

            System.err.println("Finished with socket, waiting for next connection.");
        }
    }

    public static void main(String argv[]) {
        int port = 54321;
        VerySimpleServer server = new VerySimpleServer(port);
        server.waitForConnections();
    }

我的问题是:

  1. 当我使用时sockOutput.write,我可以在回来找回这些消息sockInput.read。因此,这些消息已保存,对不对?如果为true,则将其保存在我创建的服务器上还是仅保存在其他内容中,例如Socket Object

  2. 如果我已经向套接字String A1,A2,…写了,那么我将分别收到A1,A2,…一个String,对吗?


问题答案:

套接字是一种抽象概念,可用于与网络上的某些事物进行通信。见下图…

在Java中,要通过套接字发送数据,您需要从中获得OutputStream(1),然后写入OutputStream(输出一些数据)。

要从套接字读取数据,请获取其InputStream,然后从第二个流中读取输入。

您可以将这些流视为连接到墙上插座的 一对单向 管道。在墙的另一侧发生的事情不是您的问题!

在您的情况下,服务器具有另一个套接字(连接的另一端)和另一对流。它使用InputStream(2)从网络读取数据,并使用OutputStream(3)通过网络将
相同的 数据写回到您的客户端,客户端通过InputStream(4)完成往返来再次读取数据。

      Client                                                     Server

1. OutputStream -->\                                     /--> 2. InputStream -->
                    Socket <--> network <--> ServerSocket                       |
4. InputStream  <--/                                     \<--3. OutputStream <--

更新: 回复评论:

请注意,流和套接字仅发送原始字节。在这种抽象级别上,他们没有“消息”的概念。因此,如果您发送X个字节和另外X个字节,然后读取X个字节并读取另一个X个字节,则系统的行为就好像有两条消息一样,因为这就是您将字节分割的方式。

如果您发送X个字节,再发送另外X个字节,然后读取长度为2X的答复,那么您 也许
可以读取单个组合的“消息”,但是正如您已经注意到的,流的基础实现可以选择何时交付大块字节,因此它可能返回X字节,然后再返回X字节,或者一次返回2X,或者四次返回0.5X



 类似资料:
  • 我使用创建了一个服务器。之后,我使用创建了客户机,并连接到该服务器。 之后,我对InputStream做了“一些事情”,而OutputStream是从套接字对象中获取的。但是,我不太理解inputStream和outputStream。下面是我的简单代码: 结果将是:“Hello World”和“Hello StackOverflow”。 以下是服务器端代码: 我的问题是: > 当我使用时,我可以

  • 我已经开发了Android应用程序,并且连接到JAVA Web Socket,基本上它运行得很好。问题是,有时客户端断开连接,但服务器端的连接似乎已连接。 我试图调查它发生的时间和原因,但不幸的是,我找不到导致这个问题的具体情况。 我想在服务器和所有客户端之间实现乒乓消息,如果客户端没有响应,就关闭服务器端的连接。 我可以很容易地实现这样的我的私人机制,但我已经阅读了周围,我知道Java和Andr

  • 计算机网络基础 ip地址 为了使网络上的计算机能够彼此识别对方,每台计算机都需要一个IP地址以标识自己。 IPv4:32位,IPv6:64位 OSI七层参考模型 应用层 表示层 会话层 传输层 网络层 数据链路层 物理层 地址解析 地址解析是指将计算机的协议地址解析为物理地址,即MAC(Medium Access Control)地址,又称为媒体访问控制地址。通常,在网络上由地址解析协议(ARP)

  • 本文向大家介绍Java套接字(Socket)网络编程入门,包括了Java套接字(Socket)网络编程入门的使用技巧和注意事项,需要的朋友参考一下 网络应用模式主要有: 主机/终端模式:集中计算,集中管理; 客户机/服务器(Client/Server,简称C/S)模式:分布计算,分布管理; 浏览器/服务器模式:利用Internet跨平台。 www(万维网)就是建立在客户机/服务器模式上,以HTML

  • 函数 描述 [[socket socket]] 创建一个套接字描述符 [[socketpair socketpair]] 创建一个套接字偶对 [[shutdown shutdown]] 断开套接字连接 [[close close]] 销毁套接字 套接字选项 函数 描述 [[getsockopt sockopt]] [[setsockopt sockopt]] 适用于流式套接字和数据报套接字 流套接

  • 套接字地址结构 地址结构 说明 sockaddr_un UNIX通信域套接字地址 sockaddr_in IPv4套接字地址 sockaddr_in6 IPv6套接字地址 sockddr_un struct sockaddr_un { sa_familly_t sun_family; char sun_path[]; } sockaddr_in /* 在头文件<netinet/in