簡體   English   中英

套接字問題 - 僅讀取第一條消息

[英]Socket Issue - Only first message read

我對套接字很陌生,希望有人能幫助我。 我有一些工作,但它沒有很快發送信息,所以我已經重構,現在無法恢復任何工作。 問題似乎是只有發布的第一條消息被讀取,然后接收者位於client = listener.accept(); 盡管我很確定發件人仍在發送消息

誰能看到我在這里做錯了什么?

謝謝

  public class Sender {
        Socket server = null;
        DataInputStream inp = null;
        PrintStream outp = null;

        public Sender(){
            server = new Socket("127.0.0.1" , 3456);
            outp = new PrintStream(server.getOutputStream());
        }

        private void connectAndSendToServer(String message)  {
            outp = new PrintStream(server.getOutputStream());
            outp.print(message + "\n");
            outp.flush();

        }
    }

接收器類

public class Receive{


    public String receiveMessage(int port) {
        String message= null;
        ServerSocket listener = null;
        Socket client = null;
        try{
            listener = new ServerSocket(port);
            client = listener.accept();         
            BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
            return br.readLine();

        }
        ...
        finally{
            try {
                if(client!=null && listener!=null){
                    client.close();
                    listener.close();
                }
            } 
            catch (IOException e) {

            }
        }
        return message;
    }
}

這是因為ServerSocket被用作普通 Socket 的入口點。 accept()是一種阻塞操作,與接收/發送數據到普通Socket的線程相比,它通常在不同的線程上完成。 它坐在那里等待新連接產生一個新的Socket ,然后用於數據。

這意味着在接收消息時,您應該只調用 readLine() 來從特定的套接字中讀取。 receiveMessage中有一個accept是錯誤的,因為它是一個不同的操作,它甚至是阻塞的。

Socket socket = serverSocket.accept();

ClientThread thread = new ClientThread(socket);

class ClientThread extends Thread {
  Socket socket;

  public void run() {
    while (!closed) {
      String line = reader.readLine();
      ...
    }
  }

雖然你不需要為每個客戶端都有一個線程,但如果你想讓你的服務器接受大於 1 的連接數,你至少需要兩個線程。

您沒有正確使用 ServerSocket。 您不應該為每條消息創建一個新實例,而是可以將其用作數據成員並運行無限循環以獲取新的客戶端套接字連接。 因為您在本地創建它,所以當您從該方法返回時,套接字將關閉,因為不再使用和引用該對象(因此 GC)。
類似的東西(<條件滿足>是偽代碼定義了你接受新連接的條件):

while(< condition met >) {
    try {
        client = listener.accept();
        BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
        String str = br.readLine();
        //do something with str
    } finally {
        //close client socket
    }    
}

更好的方法是在不同的線程中處理客戶端套接字,以便主線程返回接受,同時您可以並行地對客戶端套接字執行任何操作。

試試我寫的這個基本的聊天服務器。 該服務器只是保持循環運行,並將客戶端發送的消息廣播到與該服務器關聯的所有其他客戶端。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class Server {

    // ///----------------------------------------Instance Variable Fields
    ServerSocket ss = null;
    Socket incoming = null;

    // ///----------------------------------------Instance Variable Fields

    // ///---------------------------------------- static Variable Fields
    public static ArrayList<Socket> socList = new ArrayList<Socket>();

    // ///---------------------------------------- static Variable Fields

    public void go() {

        try {

            ss = new ServerSocket(25005);

            while (true) {

                incoming = ss.accept();
                socList.add(incoming);
                System.out.println("Incoming: " + incoming);
                new Thread(new ClientHandleKaro(incoming)).start();

            }

        } catch (IOException e) {

            e.printStackTrace();
        } finally {

            try {
                ss.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

    class ClientHandleKaro implements Runnable {

        InputStream is = null;
        OutputStream os = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        PrintWriter pw = null;
        boolean isDone = false;

        Socket sInThread = null;

        public ClientHandleKaro(Socket sxxx) {

            this.sInThread = sxxx;

        }

        @Override
        public void run() {

            if (sInThread.isConnected()) {

                System.out.println("Welcamu Clienta");
                System.out.println(socList);
            }

            try {
                is = sInThread.getInputStream();
                System.out.println("IS: " + is);
                isr = new InputStreamReader(is);
                br = new BufferedReader(isr);

                os = sInThread.getOutputStream();
                pw = new PrintWriter(os, true);

                String s = new String();

                while ((!isDone) && (s = br.readLine()) != null) {

                    String[] asx = s.split("-");
                    System.out.println("On Console: " + s);

                    // pw.println(s);

                    Thread tx = new Thread(new ReplyKaroToClient(s,
                            this.sInThread));
                    tx.start();

                    if (asx[1].trim().equalsIgnoreCase("BYE")) {

                        System.out.println("I am inside Bye");
                        isDone = true;

                    }
                }
            } catch (IOException e) {

                System.out.println("Thanks for Chatting.....");
            } finally {

                try {
                    Thread tiku = new Thread(new ByeByeKarDo(sInThread));
                    tiku.start();
                    try {
                        tiku.join();
                    } catch (InterruptedException e) {

                        e.printStackTrace();
                    }

                    System.out.println("Accha to hum Chalte hain !!!");
                    System.out.println(socList);

                    br.close();
                    pw.close();
                    sInThread.close();

                } catch (IOException e) {

                }
            }

        }

    }

    class ReplyKaroToClient implements Runnable {

        public String mString;
        public Socket mSocket;

        public ReplyKaroToClient(String s, Socket sIn) {

            this.mString = s;
            this.mSocket = sIn;
        }

        @Override
        public void run() {

            for (Socket sRaW : socList) {

                if (mSocket.equals(sRaW)) {
                    System.out.println("Mai same hun");
                    continue;

                } else {
                    try {
                        new PrintWriter(sRaW.getOutputStream(), true)
                                .println(mString);
                    } catch (IOException e) {

                        System.out.println("Its in Catch");

                    }
                }
            }

        }

    }

    class ByeByeKarDo implements Runnable {

        Socket inCom;

        public ByeByeKarDo(Socket si) {

            this.inCom = si;
        }

        @Override
        public void run() {

            try {
                new PrintWriter(inCom.getOutputStream(), true)
                        .println("You have Logged Out of Server... Thanks for your Visit");
            } catch (IOException e) {

                e.printStackTrace();
            }

        }

    }

    public static void main(String[] args) {

        new Server().go();
    }
}

暫無
暫無

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

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