繁体   English   中英

简单服务器/客户端套接字:阻塞-Java

[英]Simple Server/Client Socket: BLOCKING - Java

我有一个客户端和一个服务器,这是一个经典示例,尝试以非常简单的方式模拟http协议。 首先,客户端发送数据,而服务器打印数据,然后相反。 在以下代码中,由于未知原因,服务器或客户端都将阻塞。 客户端向服务器发送数据,服务器接收数据并打印。 但是它只是在打印数据后阻塞。 如果我关闭客户端的输出流(out.close()),则客户端应获取服务器的数据,但会抛出IOException并显示以下消息:套接字已关闭。

我的问题是为什么它会阻塞? 我必须使用EOS触发输出吗?

客户

import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.util.*;
import java.io.IOException;
import java.io.*;


public class block_client_webclient
{
    public static void main(String [] args)
    {
        try{

            Socket s = new Socket("localhost", 8080);

            OutputStreamWriter out = new OutputStreamWriter(s.getOutputStream());
            InputStreamReader in = new InputStreamReader(s.getInputStream());

            //WRITE
            out.write("GET / HTTP/1.1\r\nUser-agent: Agent 2.0 Browser\r\nAccept: */*\r\nAccept-Language: en-US,en;q=0.5\r\nConnection: keep-alive\r\n\r\n");
            out.flush();
            out.close();

            if (s.isConnected()==true && s.isClosed()==false) System.out.println("OPEN");
            else System.out.println("CLOSED");

            char[] bin = new char[400];
            int r=0;

            //READ
            while((r=in.read(bin))!=-1) { System.out.println("Input data: "+r+" bytes"); System.out.print(bin); bin= new char[400]; };
            System.out.println(r);

            s.close();

        }
        catch (IOException ex) {System.out.println(ex.getMessage());}
    }
}

服务器

import java.nio.*;
import java.nio.channels.*;
import java.net.*;
import java.util.*;
import java.io.IOException;
import java.io.*;


public class block_server_webserver
{
    public static void main(String [] args)
    {
        while(true)
        {
        try{
            ServerSocket server = new ServerSocket(8080);
            Socket connection = server.accept();
            try{
            OutputStreamWriter out = new OutputStreamWriter( connection.getOutputStream());
            InputStreamReader in = new InputStreamReader( connection.getInputStream());

            char[] bin = new char[400];
            int r=0;
            int readsofar=0;

            //READ
            while((r=in.read(bin))!=-1) { System.out.print(bin); bin= new char[400]; };
            System.out.println("END");

            //WRITE
            out.write("Server: BlockServer 1.0\r\nHost: 192.168.1.1\r\n\r\n");
            out.flush();
            System.out.println("Just written data to "+connection.getRemoteSocketAddress());
            connection.close();

            } catch (IOException ex) { connection.close();}
        }catch (IOException ex) {}
     }
    }
}

服务器不应等待套接字关闭(因为一旦发生这种情况,它将无法回写)。

与其读取直到返回-1(关闭),不如读取到请求的末尾(对于HTTP标头为两行),并在发生这种情况后立即开始发送输出,然后可能会关闭连接以通知客户端没有更多数据(在http中,连接通常保持打开状态一段时间,根据Content-length标头接收到足够的字节后,客户端知道停止读取)。

执行out.close()会导致套接字关闭异常,因为当您关闭输入/输出流时,与此相关的套接字也会被关闭。 这意味着在客户端程序中,关闭套接字后将无法读入。

首先,取出out.close()而不是检查-1,而是尝试创建一个“退出”字符串。 如果服务器读取了退出字符串,请认识到它需要停止在while循环中并中断。 (可以使用简单的if语句完成)。 另外,通常我会使用缓冲的读取器,String x和readLine()而不是char数组+ read()。

while (true) {
    in.read(bin);
    if (bin[0] == '^') { // or something like that
        break;
    }
    System.out.print(bin);
    bin = new char[400];
}

完全使用完套接字后,只有close()流。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM