简体   繁体   English

套接字问题 - 仅读取第一条消息

[英]Socket Issue - Only first message read

I am very new to sockets and was hoping someone could help me.我对套接字很陌生,希望有人能帮助我。 I had something working but it was not sending information very quickly so i have refactored and now cannot get back to anything which works.我有一些工作,但它没有很快发送信息,所以我已经重构,现在无法恢复任何工作。 The issue seems to be that only the first message that is published is read and then the receiver sits on client = listener.accept();问题似乎是只有发布的第一条消息被读取,然后接收者位于client = listener.accept(); even though im pretty sure the sender is still sending messages尽管我很确定发件人仍在发送消息

Can anyone see what i might be doing wrong here please?谁能看到我在这里做错了什么?

Thanks谢谢

  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();

        }
    }

Receiver class接收器类

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;
    }
}

This because a ServerSocket is used as an entry point for a normal Socket.这是因为ServerSocket被用作普通 Socket 的入口点。 accept() is a blocking operation that is usually done on a different thread compared to the one that receives/sends data to normal Socket . accept()是一种阻塞操作,与接收/发送数据到普通Socket的线程相比,它通常在不同的线程上完成。 It sits there and waits for a new connection to spawn a new Socket which is then used for data.它坐在那里等待新连接产生一个新的Socket ,然后用于数据。

This means that while receiving messages you should call just readLine() to read from the specific Socket.这意味着在接收消息时,您应该只调用 readLine() 来从特定的套接字中读取。 Having an accept inside the receiveMessage is wrong just because it's a different operation and it's even blocking.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();
      ...
    }
  }

You don't need to have a thread for every client though, but you need at least two for sure if you want to make your server accept a number of connections greater than 1.虽然你不需要为每个客户端都有一个线程,但如果你想让你的服务器接受大于 1 的连接数,你至少需要两个线程。

You are not using ServerSocket correctly.您没有正确使用 ServerSocket。 You shouldn't create a new instance for every message but use it as a data member maybe and run an infinite loop to get a new client socket connection.您不应该为每条消息创建一个新实例,而是可以将其用作数据成员并运行无限循环以获取新的客户端套接字连接。 Because you create it locally, the socket is closed since the object is no longer used and referenced (and so GC'ed), when you return from the method.因为您在本地创建它,所以当您从该方法返回时,套接字将关闭,因为不再使用和引用该对象(因此 GC)。
Something like (< condition met > is pseudo-code defines your condition to accept new connections):类似的东西(<条件满足>是伪代码定义了你接受新连接的条件):

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
    }    
}

Better approach will be to handle client socket in a different thread so the main thread is back to accept while you can do anything with the client socket in parallel.更好的方法是在不同的线程中处理客户端套接字,以便主线程返回接受,同时您可以并行地对客户端套接字执行任何操作。

Try this basic Chatting Server written by me.试试我写的这个基本的聊天服务器。 This server simply keeps running in loop and broadcast the message send by the clients to all the other clients associated with this server.该服务器只是保持循环运行,并将客户端发送的消息广播到与该服务器关联的所有其他客户端。

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