简体   繁体   English

客户端未向服务器 Java Socket 发送消息

[英]Client side is not sending message to server Java Socket

I am learning about sockets in java, but when I was running a program that sends messages from the client side to server side it doesn't show a message.我正在学习 java 中的套接字,但是当我运行一个从客户端向服务器端发送消息的程序时,它没有显示消息。 If I enter some text on the client side it doesn't show up on the server side, but if I type endProcess it stops running.如果我在客户端输入一些文本,它不会显示在服务器端,但如果我输入 endProcess 它会停止运行。 Which means that the message is going through it's just not showing up.这意味着消息正在通过它只是没有显示出来。

My Client.java code is here:我的 Client.java 代码在这里:

import java.net.*;
import java.io.*;

public class Client{
  Socket soc;
  DataInputStream dis;
  DataOutputStream dos;

  public Client(){
    try{
      soc = new Socket("(Address)",5000);
      System.out.println("Connection Established");
      dis = new DataInputStream(System.in);
      dos = new DataOutputStream(soc.getOutputStream());
      System.out.println("Streams connected");
    }catch(UnknownHostException u){
      System.out.println(u);
    }catch(IOException i){
      System.out.println(i);
    }

    String line = "";

    while(!line.equals("endConnection")){
      try{
        line = dis.readUTF();
        dos.writeUTF(line);
      }catch(IOException i){
        System.out.println(i);
      }
    }

    try {
        soc.close();
        dis.close();
        dos.close();
    } catch (Exception e) {
        System.out.println(e)    
    }
  }
  public static void main(String[] args) {
      new Client();
  }
}

Here is my Server.java code:这是我的 Server.java 代码:

import java.net.*;
import java.io.*;

public class Server {
    ServerSocket serSoc;
    Socket soc;
    DataInputStream dis;

    public Server(){
        try {
            serSoc = new ServerSocket(5000);

            System.out.println("Server Online");

            soc = serSoc.accept();
            System.out.println("Client Connected");

            dis = new DataInputStream(new BufferedInputStream(soc.getInputStream()));
        
            String line = "";
            System.out.println("Waiting for input...");
            while(!line.equals("endConnection")){
                line = dis.readUTF();
                System.out.println(line);
            }
            System.out.println("Client disconnected");

            soc.close();
            dis.close();
        } catch (Exception e) {
            System.out.println(e);
        }
        

    }
    public static void main(String[] args) {
        new Server();
    }
}

There are many problems here.这里有很多问题。

Duplex protocol issues双工协议问题

line = dis.readUTF(); dos.writeUTF(line);

This isn't going to work;这是行不通的; The dis.readUTF() line is going to block (freeze) until a line is read. dis.readUTF()行将阻塞(冻结),直到读取一行。 The problem is, sometimes you have nothing to send in which case you want to read, and something you have nothing to read in which case you want to send.问题是,有时在您想阅读的情况下您没有什么可发送的,而在您想发送的情况下您没有什么可阅读的。 In practice you need to redesign this entirely;在实践中,您需要完全重新设计它; you need 2 threads.你需要2个线程。 At which point you get into the issues of multicore, needing synchronization primitives and/or java.util.concurrent classes for all data that is shared between the 2 threads.此时您会遇到多核问题,需要同步原语和/或java.util.concurrent类来处理两个线程之间共享的所有数据。

Alternatively, adopt a model that is strictly push or pull (where at any given time both parties already know who can send, and if the other party wants to send they simply cannot. For example, every party sends a simply 'NOTHING TO DO' message every second, trading places every time. This is quite an inefficient algorithm, of course. But could be written without involving multiple threads.或者,采用严格推或拉的模型(在任何给定时间,双方都已经知道谁可以发送,如果对方想要发送,他们根本就不能发送。例如,每一方都发送一个简单的“NOTHING TO DO”每秒消息,每次交换位置。当然,这是一个效率很低的算法。但是可以在不涉及多个线程的情况下编写。

Flush and close issues刷新和关闭问题

dos.writeUTF(line);

This doesn't actually send anything, or at least, isn't guaranteed to.这实际上并没有发送任何东西,或者至少不能保证发送任何东西。 To send any data on the internet, it gets wrapped in a packet which has lots of overhead.要在互联网上发送任何数据,它会被包装在一个具有大量开销的数据包中。 So, things are buffered until there's a full packet to send.所以,事情会被缓冲,直到有一个完整的数据包要发送。 Which means that line doesn't do anything.这意味着该行不执行任何操作。 It just fills a buffer, no packets go out.它只是填充一个缓冲区,没有数据包出去。 You first need to close or flush.您首先需要关闭或冲洗。 dos.flush() would help maybe. dos.flush()可能会有所帮助。 This is a big problem, because later you do:这是一个大问题,因为稍后你会这样做:

 soc.close(); dis.close(); dos.close();

You first close the socket, which, well, closes the socket .您首先关闭套接字,然后关闭套接字 You then close the streams, which will also send anything that's still stuck in a buffer, except, that will fail, because the socket is already closed.然后关闭流,这也将发送仍然卡在缓冲区中的任何内容,但由于套接字已经关闭,这将失败。 In other words, the line you .writeUTF() -ed?换句话说,你.writeUTF()的那一行? It never gets there.它永远不会到达那里。 You first shove it in a buffer, then you close the socket, then you send the buffer which won't work as the socket is already closed.您首先将其推入缓冲区,然后关闭套接字,然后发送缓冲区,由于套接字已经关闭,该缓冲区将不起作用。

Broken error handling中断错误处理

} catch (Exception e) { System.out.println(e); }

Horrible.可怕。 Don't do this.不要这样做。 Your code reacts to any problem by printing something and just keeping right on going .您的代码通过打印某些内容并继续运行来对任何问题做出反应。 That means if anything goes wrong, the client will start spamming an endless cavalcade of exception traces and locking up the system with any luck.这意味着如果出现任何问题,客户端将开始向无休止的异常跟踪行列发送垃圾邮件并锁定系统,如果运气好的话。 You want the code to stop running when problems occur.您希望代码在出现问题时停止运行。 Easiest way, by far, is to just stick throws IOException on your constructor and main method, which is allowed.到目前为止,最简单的方法是将throws IOException粘贴在您的构造函数和 main 方法上,这是允许的。 Distant second best option is to configure your 'eh whatever' catch blocks as throw new RuntimeException("unhandled", e);遥远的第二个最佳选择是将您的“ehwhatever”捕获块配置为throw new RuntimeException("unhandled", e); instead of e.printStackTrace() .而不是e.printStackTrace()

What you do ( System.out.println(e); ) is even worse - you are tossing away extremely useful information such as the stack trace and causal chain.你所做的( System.out.println(e);更糟糕- 你正在丢弃非常有用的信息,例如堆栈跟踪和因果链。

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

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