java - 多个客户端线程可以连接,线程按顺序接受

标签 java multithreading sockets

我正在尝试编写一个投标应用程序,并有一个服务器(和线程处理程序)和客户端(和客户端处理程序)。 目前,多个客户端可以正常连接,但第一个连接的客户端会获取开始消息,并且只有在第一个客户端进行第三次交互(客户端和服务器之间)后,列表中的下一个客户端才会获取开始消息。 我不完全确定是什么原因造成的,因为它每次都会添加一个新线程。它只是没有同时向所有客户端显示 writeUTF() 的内容。

我想知道我做错了什么,以及为什么我无法让多个客户同时开始拍卖。这是我的代码。 客户端线程和客户端

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

public class Client implements Runnable
{  private Socket socket              = null;
   private Thread thread              = null;
   private BufferedReader  console   = null;
   private DataOutputStream streamOut = null;
   private ClientThread client    = null;
   private String chatName;


   public Client(String serverName, int serverPort, String name)
   {
      System.out.println("Establishing connection. Please wait ...");

      this.chatName = name;
      try{
         socket = new Socket(serverName, serverPort);
         System.out.println("Connected: " + socket);
         start();
      }
      catch(UnknownHostException uhe){
          System.out.println("Host unknown: " + uhe.getMessage());
      }
      catch(IOException ioe){
          System.out.println("Unexpected exception: " + ioe.getMessage());
      }
   }

   public void run()
   {
       while (thread != null){
         try {
            //String message = chatName + " > " + console.readLine();
            String message = console.readLine();
            streamOut.writeUTF(message);
            streamOut.flush();
         }
         catch(IOException ioe)
         {  System.out.println("Sending error: " + ioe.getMessage());
            stop();
         }
      }
   }

   public void handle(String msg)
   {  if (msg.equals(".bye"))
      {  System.out.println("Good bye. Press RETURN to exit ...");
         stop();
      }
      else
         System.out.println(msg);
   }

   public void start() throws IOException
   {
      console = new BufferedReader(new InputStreamReader(System.in));

      streamOut = new DataOutputStream(socket.getOutputStream());
      if (thread == null)
      {  client = new ClientThread(this, socket);
         thread = new Thread(this);
         thread.start();
      }
   }

   public void stop()
   {
      try
      {  if (console   != null)  console.close();
         if (streamOut != null)  streamOut.close();
         if (socket    != null)  socket.close();
      }
      catch(IOException ioe)
      {
          System.out.println("Error closing ...");

      }
      client.close();
      thread = null;
   }


   public static void main(String args[])
   {  Client client = null;
      if (args.length != 3)
         System.out.println("Usage: java Client host port name");
      else
         client = new Client(args[0], Integer.parseInt(args[1]), args[2]);
   }
}

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

客户端线程

public class ClientThread extends Thread
{  private Socket           socket   = null;
   private Client       client   = null;
   private DataInputStream  streamIn = null;
   private DataOutputStream streamOut = null;
   private BufferedReader console;
   private String message, bidMessage;




    public ClientThread(Client _client, Socket _socket)
       {  client   = _client;
          socket   = _socket;
          open();
          start();
       }
       public void open()
       {  try
          {
              streamIn  = new DataInputStream(socket.getInputStream());
              String auction = streamIn.readUTF(); // Commence auction/
              System.out.println(auction);
              String item = streamIn.readUTF();
              System.out.println(item);

              Scanner scanner = new Scanner(System.in);
              streamOut = new DataOutputStream(socket.getOutputStream());
              message = scanner.next();
              streamOut.writeUTF(message);
              streamOut.flush();

             String reply = streamIn.readUTF();
             System.out.println(reply);






             bidMessage = scanner.next();
             streamOut.writeUTF(bidMessage);
             streamOut.flush();



          }
          catch(IOException ioe)
          {
             System.out.println("Error getting input stream: " + ioe);
             client.stop();
          }
       }
       public void close()
       {  try
          {  if (streamIn != null) streamIn.close();
          }
          catch(IOException ioe)
          {  System.out.println("Error closing input stream: " + ioe);
          }
       }

       public void run()
       {
           while (true && client!= null){
              try {

                  client.handle(streamIn.readUTF());
              }
              catch(IOException ioe)
              {
                  client = null;
                  System.out.println("Listening error: " + ioe.getMessage());

             }
          }
       }
    }

出价服务器

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

public class BidServer implements Runnable
{  

   // Array of clients  
   private BidServerThread clients[] = new BidServerThread[50];
   private ServerSocket server = null;
   private Thread       thread = null;
   private int clientCount = 0;

   public BidServer(int port)
   {
      try {

         System.out.println("Binding to port " + port + ", please wait  ...");
         server = new ServerSocket(port);
         System.out.println("Server started: " + server.getInetAddress());
         start();
      }
      catch(IOException ioe)
      {
          System.out.println("Can not bind to port " + port + ": " + ioe.getMessage());

      }
   }

   public void run()
   {
      while (thread != null)
      {
         try{

            System.out.println("Waiting for a client ...");

            addThread(server.accept());

            int pause = (int)(Math.random()*3000);
            Thread.sleep(pause);

         }
         catch(IOException ioe){
            System.out.println("Server accept error: " + ioe);
            stop();
         }
         catch (InterruptedException e){
            System.out.println(e);
         }
      }
   }

  public void start()
    {
        if (thread == null) {
          thread = new Thread(this);
          thread.start();
       }
    }

   public void stop(){
       thread = null;

   }

   private int findClient(int ID)
   {
       for (int i = 0; i < clientCount; i++)
         if (clients[i].getID() == ID)
            return i;
      return -1;
   }

   public synchronized void broadcast(int ID, String input)
   {
       if (input.equals(".bye")){
          clients[findClient(ID)].send(".bye");
          remove(ID);
       }
       else
         for (int i = 0; i < clientCount; i++){
            if(clients[i].getID() != ID)
                clients[i].send(ID + ": " + input); // sends messages to clients
        }
       notifyAll();
   }
   public synchronized void remove(int ID)
   {
      int pos = findClient(ID);
      if (pos >= 0){
         BidServerThread toTerminate = clients[pos];
         System.out.println("Removing client thread " + ID + " at " + pos);

         if (pos < clientCount-1)
            for (int i = pos+1; i < clientCount; i++)
               clients[i-1] = clients[i];
         clientCount--;

         try{
             toTerminate.close();
         }
         catch(IOException ioe)
         {
             System.out.println("Error closing thread: " + ioe);
         }
         toTerminate = null;
         System.out.println("Client " + pos + " removed");
         notifyAll();
      }
   }

   private void addThread(Socket socket) throws InterruptedException
   {
      if (clientCount < clients.length){

         System.out.println("Client accepted: " + socket);
         clients[clientCount] = new BidServerThread(this, socket);
         try{
            clients[clientCount].open();
            clients[clientCount].start();
            clientCount++;
         }
         catch(IOException ioe){
             System.out.println("Error opening thread: " + ioe);
          }
      }
      else
         System.out.println("Client refused: maximum " + clients.length + " reached.");
   }


   public static void main(String args[]) {
       BidServer server = null;
      if (args.length != 1)
         System.out.println("Usage: java BidServer port");
      else
         server = new BidServer(Integer.parseInt(args[0]));
   }

}

出价服务器线程

import java.net.*;
import java.awt.List;
import java.io.*;
import java.awt.*;
import java.util.*;
import java.util.concurrent.BrokenBarrierException;


public class BidServerThread extends Thread
{  private BidServer       server    = null;
   private Socket           socket    = null;
   private int              ID        = -1;
   private DataInputStream  streamIn  =  null;
   private DataOutputStream streamOut = null;
   private Thread thread;
   private String auctionStart, bid,bidMade,clientBid;
   private String  invalidBid;
   int firstVal;

   ArrayList<Bid> items = new ArrayList<Bid>();
   //items.add(new Bid());
   //items

   //items
   //items.add(new Bid("Red Bike",0));






   public BidServerThread(BidServer _server, Socket _socket)
   {
      super();
      server = _server;
      socket = _socket;
      ID     = socket.getPort();



   }
   public void send(String msg)
   {
       try{

          streamOut.writeUTF(msg);
          streamOut.flush();
       }
       catch(IOException ioe)
       {
          System.out.println(ID + " ERROR sending: " + ioe.getMessage());
          server.remove(ID);
          thread=null;
       }
   }
   public int getID(){
       return ID;
   }

   public void run()
   {
      System.out.println("Server Thread " + ID + " running.");
      thread = new Thread(this);
      while (true){
         try{
             server.broadcast(ID, streamIn.readUTF());

             int pause = (int)(Math.random()*3000);
             Thread.sleep(pause);
         }
         catch (InterruptedException e)
         {
            System.out.println(e);
         }
         catch(IOException ioe){
            System.out.println(ID + " ERROR reading: " + ioe.getMessage());
            server.remove(ID);
            thread = null;
         }
      }
   }

   public void open() throws IOException, InterruptedException
   {
      streamIn = new DataInputStream(new
                        BufferedInputStream(socket.getInputStream()));

      streamOut = new DataOutputStream(new
                        BufferedOutputStream(socket.getOutputStream()));
      String msg2 = "Welcome to the auction,do you wish to start?";
    streamOut.writeUTF(msg2);
    streamOut.flush();
    String auctionStart;
    String bid;
    String firstMessage = streamIn.readUTF().toLowerCase();
    CharSequence yes ="yes";
    CharSequence no = "no";
    if(firstMessage.contains(yes))
    {

      commenceBid();


    }

    else if(firstMessage.contains(no))
    {
        auctionStart ="Unfortunately, you cannot proceed. Closing connection";
        System.out.println(auctionStart);
        streamOut.writeUTF(auctionStart);
        streamOut.flush();
        int pause = (int)(Math.random()*2000);
        Thread.sleep(pause);
        socket.close();


    }
    else if(!firstMessage.contains(yes) && !firstMessage.contains(no)) 
    {
        System.out.println("Client has entered incorrect data");
        open();
    }


   }

   private void commenceBid() throws IOException {


         items.add(new Bid("Yellow Bike",0));
         items.add(new Bid("Red Bike",0));
         //items.add(new Bid("Green bike",0));


         String auctionStart = "Auction will commence now. First item is:\n" + items.get(0).getName();
         String bidCommence = "Make a bid, whole number please.";
         synchronized (server) {
                server.broadcast(ID, bidCommence);
         }

         System.out.println("item value is" + items.get(0).getValue());
         streamOut.writeUTF(auctionStart);
         streamOut.flush();
         streamOut.writeUTF(bidCommence);
         streamOut.flush();

         bidMade();


}
private void bidMade() throws IOException {

     bidMade = streamIn.readUTF();

     if(bidMade.matches(".*\\d.*"))
     {
         int bid = Integer.parseInt(bidMade); 

         if(bid <= items.get(0).getValue())
         {
             String lowBid = "Latest bid is too low, please bid higher than the current bid " + items.get(0).getValue();
             streamOut.writeUTF(lowBid);
             streamOut.flush();

             commenceBid();
         }
         if (bid > items.get(0).getValue()) {

             items.get(0).setValue(bid);
             String bidItem = "value of current bid is: " + items.get(0).getValue();
             streamOut.writeUTF(bidItem);
             streamOut.flush();
             System.out.println("Current bid: " + items.get(0).getValue());
             String continueBid = "If you want to make another bid, say yes";
             streamOut.writeUTF(continueBid);
             String continueBidReply = streamIn.readUTF();
             {
                 if(continueBidReply.contains("yes") || continueBidReply.contains("Yes"))
                 {
                     commenceBid();
                 }
                 if(continueBidReply.contains("No") || continueBidReply.contains("No"))
                 {
                     socket.close();
                 }
             }
             streamOut.flush();

        }


     }   

     else
     {
          invalidBid = "You have made an invalid bid, please choose a number";
          streamOut.writeUTF(invalidBid);
          streamOut.flush();


     }


}
public void close() throws IOException
   {
       if (socket != null)
        socket.close();

      if (streamIn != null)
        streamIn.close();

      if (streamOut != null)
        streamOut.close();
   }
}

最佳答案

BidServerThread.open()BidServer.addThread() 中启动线程之前调用。这会阻止 BidServer(并阻止其接受其他客户端),直到调用返回。

BidServerThread.open() 执行与客户端交互的各种同步操作(“您希望开始吗?”、"is"/“否”等)。它最终递归地调用自身(循环),并调用 commenceBid(),而 commenceBid() 又可能调用 bidMade(),而 bidMade() 又可能在与客户端的同步交互过程中递归到 commenceBid()。在这种情况下,您可能会在结束之前进行 3 次交互。

我想,您可以从 BidServerThread.run() 而不是在 BidServer.addThread() 中调用 BidServerThread.open() ,以便它在其线程中异步运行。 (Thread.start() 调用 Thread.run()。)

关于java - 多个客户端线程可以连接,线程按顺序接受,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20000703/

相关文章:

java - 加密 MYSQL DB 中的值

java - 一对多 Spring 结果映射

java - Sun/Oracle CORBA 实现是否有线程池以及如何配置它?

Java:客户端套接字不读取第二行并在终止符行之后保持打开状态

c# - FIFO编程的主线程调度程序?

c++ - 套接字错误无法在 WinSock2.h 中获取函数

java - 如何在Java中延迟声音

java - Hibernate 为带有 JoinTable 的可选双向 OneToOne 生成错误查询

java - 处理程序更改 UI 导致 CalledFromWrongThreadException

java - 取消套接字和/或线程时遇到问题