Данные не синхронизируют сокеты Java - PullRequest
0 голосов
/ 19 ноября 2011

Я пишу аукционный сервер и клиент и использую класс BidHandler для обработки заявок, другой класс AuctionItem для работы с предметами для аукциона. Основная проблема, с которой я столкнулся, - это небольшая проблема с синхронизацией.

Вывод на экран клиентского сервера

Как видно из изображения на 1-м месте, он принимает новую ставку и изменяет значение времени на нее, но когда пользователь вводит 1,0, элемент, кажется, меняется на это. Но позже, когда ставка снова изменится до 15.0, она, похоже, останется по этой цене. Есть ли причина для этого. Я включил свой код ниже. Извините, если не объяснил это хорошо.

Это клиент аукциона

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

public class AuctionClient
{

private AuctionGui gui;

private Socket socket;
private DataInputStream dataIn;
private DataOutputStream dataOut;

//Auction Client constructor  String name used as identifier for each client to allow server to pick the winning bidder
public AuctionClient(String name,String server, int port)
{

    gui = new AuctionGui("Bidomatic 5000");
    gui.input.addKeyListener (new EnterListener(this,gui));
    gui.addWindowListener(new ExitListener(this));

    try
    {
        socket = new Socket(server, port);
        dataIn = new DataInputStream(socket.getInputStream());
        dataOut = new DataOutputStream(socket.getOutputStream());
        dataOut.writeUTF(name);
          while (true) 
          {
        gui.output.append("\n"+dataIn.readUTF());
        }
  } 
  catch (Exception e)   
  {
     e.printStackTrace();
  }

}




public void sentBid(String bid)
{
    try
    {
        dataOut.writeUTF(bid);
    }

    catch(IOException e)
    {
        e.printStackTrace();
    }

}

public void disconnect()
{
    try
    {
        socket.close();
    }

    catch(IOException e)
    {
        e.printStackTrace();
    }
}

public static void main (String args[]) throws IOException
{
    if(args.length!=3)
    {
        throw new RuntimeException ("Syntax: java AuctionClient <name> <serverhost> <port>");
    }

    int port = Integer.parseInt(args[2]);
    AuctionClient a = new AuctionClient(args[0],args[1],port);

}
}

Аукционный сервер

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

public class AuctionServer
{


public AuctionServer(int port) throws IOException
{
    ServerSocket server = new ServerSocket(port);

    while(true)
    {
        Socket client = server.accept();
        DataInputStream in = new DataInputStream(client.getInputStream());
        String name = in.readUTF();
        System.out.println("New client "+name+" from " +client.getInetAddress());

        BidHandler b = new BidHandler (name, client);
        b.start();
    }

}


public static void main(String args[]) throws IOException
{
    if(args.length != 1)
        throw new RuntimeException("Syntax: java AuctionServer <port>");

    new AuctionServer(Integer.parseInt(args[0]));

}


}

The BidHandler

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

public class BidHandler extends Thread
{
Socket socket;
DataInputStream in;
DataOutputStream out;
String name;
float currentBid = 0.0f;
AuctionItem paper = new AuctionItem(" News Paper ", " Free newspaper from 1990 ", 1.0f, false);
protected static Vector handlers = new Vector();

public BidHandler(String name, Socket socket) throws IOException
{
    this.name = name;
    this.socket = socket;

    in = new DataInputStream (new BufferedInputStream (socket.getInputStream()));
    out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
}

public synchronized void run()
{
    try
    {
        broadcast("New bidder has entered the room");
        handlers.addElement(this);


        while(true)
        {
            broadcast(paper.getName() + paper.getDescription()+" for sale at: " +paper.getPrice());

            while(paper.getStatus() == false)
            {


                String message = in.readUTF();
                currentBid = Float.parseFloat(message);
                broadcast("Bidder entered " +currentBid);

                if(currentBid > paper.getPrice())
                {
                    paper.setPrice(currentBid);
                    broadcast("New Higgest Bid is "+paper.getPrice());
                }

                else if(currentBid < paper.getPrice())
                {
                    broadcast("Higgest Bid is "+paper.getPrice());

                }

                else if(currentBid == paper.getPrice())
                {
                    broadcast("Higgest Bid is "+paper.getPrice());

                }

            }
        }

    }

    catch(IOException ex)
    {
        System.out.println("-- Connection to user lost.");
    }

    finally
    {
        handlers.removeElement(this);
        broadcast(name+" left");

        try
        {
            socket.close();
        }
        catch(IOException ex)
        {
            System.out.println("-- Socket to user already closed ?");

        }

    }

}

protected static void broadcast (String message)
{
    synchronized(handlers)
    {
        Enumeration e = handlers.elements();

        while(e.hasMoreElements())
        {
            BidHandler handler = (BidHandler) e.nextElement();

            try
            {

                handler.out.writeUTF(message);
                handler.out.flush();
            }

            catch(IOException ex)
            {
                handler = null;
            }
        }
    }

}



}

Класс аукциона

class AuctionItem
{
String itemName;
String itemDescription;
float itemPrice;
boolean itemStatus;

//Create a new auction item with name, description, price and status
public AuctionItem(String name, String description, float price, boolean status)
{
    itemName = name;
    itemDescription = description;
    itemPrice = price;
    itemStatus = status;
}

//return the price of the item.
public synchronized float getPrice()
{
    return itemPrice;   
}

//Set the price of the item.
public synchronized void setPrice(float newPrice)
{
    itemPrice = newPrice;
}

//Get the status of the item
public synchronized boolean getStatus()
{
    return itemStatus;

}

//Set the status of the item
public synchronized void setStatus(boolean newStatus)
{

    itemStatus = newStatus;

}

//Get the name of the item
public String getName()
{

    return itemName;

}

//Get the description of the item
public String getDescription()
{

    return itemDescription;

}


}

Существует также простой графический интерфейс, который работает нормально. Если кто-то хочет, он будет включать код GUI.

1 Ответ

0 голосов
/ 20 ноября 2011

Ваши методы AuctionItem.getPrice и AuctionItem.setPrice синхронизированы, но на самом деле этого недостаточно.

В BitHandler.run у вас часто есть какой-то if, который проверяет цену, а затем вы меняете цену. Вам необходимо синхронизировать эти две операции вместе , поскольку другой поток может изменить цену между этими двумя операциями. Например, если два потока попытаются установить новую максимальную ставку на 12,0 и 15,0, они оба определят, что они выше 1.0, и они оба установят цену, но вы можете получить setPrice(15.0) с последующим setPrice(12.0), что оставляет высокую ставку на уровне 12,0.

Вы можете использовать явную блокировку для синхронизации серии операций над ценой или определить новый синхронизированный метод changePriceIfHigherThanHighest(float newPrice).

У вас могут быть другие ошибки синхронизации; Я не проверил тщательно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...