Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java TCP客户端发送被阻止?_Java_Sockets_Tcp - Fatal编程技术网

Java TCP客户端发送被阻止?

Java TCP客户端发送被阻止?,java,sockets,tcp,Java,Sockets,Tcp,我正在编写一个与C服务器对话的java TCP客户机。 我必须在两者之间交替发送和接收。 这是我的密码 服务器向客户端(java)发送二进制消息(len)的长度 客户端发送一个“ok”字符串 服务器发送二进制文件,客户端分配一个“len”字节的字节数组来接收它 它再次返回一个“ok” 第一步。作品我得到“len”值。然而,客户端被“阻止发送”,服务器等待接收数据 有人能看一下吗 在我定义的try块中: Socket echoSocket = new Socket("192

我正在编写一个与C服务器对话的java TCP客户机。 我必须在两者之间交替发送和接收。 这是我的密码

  • 服务器向客户端(java)发送二进制消息(len)的长度
  • 客户端发送一个“ok”字符串
  • 服务器发送二进制文件,客户端分配一个“len”字节的字节数组来接收它
  • 它再次返回一个“ok” 第一步。作品我得到“len”值。然而,客户端被“阻止发送”,服务器等待接收数据

    有人能看一下吗

    在我定义的try块中:

                Socket echoSocket = new Socket("192.168.178.20",2400);
                OutputStream os = echoSocket.getOutputStream();       
                InputStream ins = echoSocket.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(ins));
    
                String fromPU = null;
    
    
                if( (fromPU = br.readLine()) !=  null){
                System.out.println("Pu returns  as="+fromPU);  
    
                len = Integer.parseInt(fromPU.trim());
                System.out.println("value of len from PU="+len);
    
                byte[] str = "Ok\n".getBytes();
                os.write(str, 0, str.length);
                os.flush();
    
                byte[] buffer = new byte[len];
                int bytes;
                StringBuilder curMsg = new StringBuilder();
                bytes =ins.read(buffer);
                System.out.println("bytes="+bytes); 
                curMsg.append(new String(buffer, 0, bytes));            
                System.out.println("ciphertext="+curMsg); 
                        os.write(str, 0, str.length);
                os.flush();
                }
    
    更新:

    这是我的密码。目前,双方都没有recv或send阻塞。然而,无论是缓冲读取器还是数据输入流读取器,我都无法发送ok消息。在服务器端,我得到大量字节,而不是ok的2个字节

                Socket echoSocket = new Socket("192.168.178.20",2400);
                OutputStream os = echoSocket.getOutputStream();   
                InputStream ins = echoSocket.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(ins));
                DataInputStream dis = new DataInputStream(ins);
                DataOutputStream dos = new DataOutputStream(os);
                if( (fromPU = dis.readLine()) !=  null){
                //if( (fromPU = br.readLine()) !=  null){
                System.out.println("PU Server returns length as="+fromPU);      
                len = Integer.parseInt(fromPU.trim());
                byte[] str = "Ok".getBytes();
                System.out.println("str.length="+str.length);
                dos.writeInt(str.length);
                if (str.length > 0) {
                        dos.write(str, 0, str.length);
                     System.out.println("sent ok");
                }
                byte[] buffer = new byte[len];
                int bytes;
                StringBuilder curMsg = new StringBuilder();
                bytes =ins.read(buffer);
                System.out.println("bytes="+bytes); 
                    curMsg.append(new String(buffer, 0, bytes));            
                    System.out.println("binarytext="+curMsg); 
    
                dos.writeInt(str.length);
                if (str.length > 0) {
                        dos.write(str, 0, str.length);
                     System.out.println("sent ok");
                }
    

    在流周围使用
    BufferedReader
    ,然后尝试从流中读取二进制数据是一个坏主意。如果服务器真的一次性发送了所有数据,并且
    BufferedReader
    读取了二进制数据以及返回的行,我也不会感到惊讶

    你能控制协议吗?如果是这样,我建议您将其更改为以二进制形式发送数据长度(例如,固定的4个字节),这样您就不需要考虑如何在文本和二进制之间切换(这基本上是一个难题)

    如果不能这样做,您可能需要一次读取一个字节,直到看到表示
    \n
    的字节,然后将读取的内容转换为文本,对其进行解析,然后将其余部分作为块读取。这有点低效(一次读取一个字节,而不是一次读取一个缓冲区),但我认为在这一点上读取的数据量相当小。

    有几种想法:

    您应该检查给定的大小与有意义的最大值。您的服务器不太可能向客户端发送2GB的消息。(可能会,但可能有更好的设计。)您通常不希望分配远程客户端要求您分配的内存量。这是一个容易进行远程拒绝服务攻击的方法

    也许您的
    BufferedReader
    吸收了太多数据?(服务器是否等待
    确定
    后再继续?)在附加
    BufferedReader
    对象后,是否确实允许您读取基础
    InputStreamReader
    对象

    请注意,TCP在接下来的两周内可以自由地以十字节块的形式交付数据:)--因为封装、不同的硬件等使得很难判断最终将在两个对等方之间使用的数据包的大小,大多数寻找特定数量数据的应用程序都会使用类似这样的代码填充缓冲区(从Unix环境中的高级编程中偷来,这是一本好书;遗憾的是,代码是C语言,代码是Java语言,但原理是一样的):

    ssize\u t/*从描述符读取“n”字节*/
    读数(内部fd,无效*ptr,尺寸)
    {
    尺寸(左);;
    ssize_t nread;
    nleft=n;
    而(nleft>0){
    如果((nread=read(fd,ptr,nleft))<0){
    如果(nleft==n)
    返回(-1);/*错误,返回-1*/
    其他的
    break;/*错误,返回到目前为止读取的金额*/
    }如果(nread==0),则为else{
    中断;/*EOF*/
    }
    nleft-=nread;
    ptr+=nread;
    }
    return(n-nleft);/*return>=0*/
    }
    

    需要注意的是,填充缓冲区可能需要对
    read()
    进行一次、十次或一百次调用,并且您的代码必须能够抵抗网络功能的轻微变化。

    您所说的“客户端被阻止发送”是什么意思?是否尝试调试?+1:另一种方法可能是将DataInputStream与readLine()和readFully()一起使用。虽然readLine()并不理想,但它可以满足OP的要求。@Peter:可能吧。它被弃用是有原因的,但这是一个好主意。我个人希望协议设计者停止以这种方式混合文本和二进制。(当然,将文本封装在一个已知大小的二进制块中是很好的。这是不同的。)IMHO,除非你非常清楚自己在做什么,否则你当然不应该将它们混合在一起。i、 e.只有在您完全理解文本和二进制文件的要求并根据需要记录协议后,才可以使用。谢谢大家。因为缓冲读取器可能是个坏主意。我现在已经将代码更改为使用DataInput Stream。不过,服务器没有收到“ok”(3字节),但似乎收到905字节!(就像上面Jon Skeet和下面Sarnold提到的那样?)我将用代码更新帖子。是的,我控制着协议。因此,也许我可以将长度改为字节。@pimmling:你试过我在回答的最后一段中的建议了吗?谢谢sarnold。一旦我修复了这个bug,我将限制字节长度。
            len = Integer.parseInt(fromPU.trim());
    
            BufferedReader br = new BufferedReader(new InputStreamReader(ins));
            /* ... */
            bytes =ins.read(buffer);
    
    ssize_t             /* Read "n" bytes from a descriptor  */
    readn(int fd, void *ptr, size_t n)
    {
        size_t      nleft;
        ssize_t     nread;
    
        nleft = n;
        while (nleft > 0) {
            if ((nread = read(fd, ptr, nleft)) < 0) {
                if (nleft == n)
                    return(-1); /* error, return -1 */
                else
                    break;      /* error, return amount read so far */
            } else if (nread == 0) {
                break;          /* EOF */
            }
            nleft -= nread;
            ptr   += nread;
        }
        return(n - nleft);      /* return >= 0 */
    }