簡體   English   中英

客戶端未向服務器 Java Socket 發送消息

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

我正在學習 java 中的套接字,但是當我運行一個從客戶端向服務器端發送消息的程序時,它沒有顯示消息。 如果我在客戶端輸入一些文本,它不會顯示在服務器端,但如果我輸入 endProcess 它會停止運行。 這意味着消息正在通過它只是沒有顯示出來。

我的 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();
  }
}

這是我的 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();
    }
}

這里有很多問題。

雙工協議問題

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

這是行不通的; dis.readUTF()行將阻塞(凍結),直到讀取一行。 問題是,有時在您想閱讀的情況下您沒有什么可發送的,而在您想發送的情況下您沒有什么可閱讀的。 在實踐中,您需要完全重新設計它; 你需要2個線程。 此時您會遇到多核問題,需要同步原語和/或java.util.concurrent類來處理兩個線程之間共享的所有數據。

或者,采用嚴格推或拉的模型(在任何給定時間,雙方都已經知道誰可以發送,如果對方想要發送,他們根本就不能發送。例如,每一方都發送一個簡單的“NOTHING TO DO”每秒消息,每次交換位置。當然,這是一個效率很低的算法。但是可以在不涉及多個線程的情況下編寫。

刷新和關閉問題

dos.writeUTF(line);

這實際上並沒有發送任何東西,或者至少不能保證發送任何東西。 要在互聯網上發送任何數據,它會被包裝在一個具有大量開銷的數據包中。 所以,事情會被緩沖,直到有一個完整的數據包要發送。 這意味着該行不執行任何操作。 它只是填充一個緩沖區,沒有數據包出去。 您首先需要關閉或沖洗。 dos.flush()可能會有所幫助。 這是一個大問題,因為稍后你會這樣做:

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

您首先關閉套接字,然后關閉套接字 然后關閉流,這也將發送仍然卡在緩沖區中的任何內容,但由於套接字已經關閉,這將失敗。 換句話說,你.writeUTF()的那一行? 它永遠不會到達那里。 您首先將其推入緩沖區,然后關閉套接字,然后發送緩沖區,由於套接字已經關閉,該緩沖區將不起作用。

中斷錯誤處理

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

可怕。 不要這樣做。 您的代碼通過打印某些內容並繼續運行來對任何問題做出反應。 這意味着如果出現任何問題,客戶端將開始向無休止的異常跟蹤行列發送垃圾郵件並鎖定系統,如果運氣好的話。 您希望代碼在出現問題時停止運行。 到目前為止,最簡單的方法是將throws IOException粘貼在您的構造函數和 main 方法上,這是允許的。 遙遠的第二個最佳選擇是將您的“ehwhatever”捕獲塊配置為throw new RuntimeException("unhandled", e); 而不是e.printStackTrace()

你所做的( System.out.println(e);更糟糕- 你正在丟棄非常有用的信息,例如堆棧跟蹤和因果鏈。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM