简体   繁体   English

多线程客户端/服务器,套接字异常

[英]Multi-threading client/server, Socket Exception

Should be a simple fix that i am not able to correct. 应该是我无法纠正的简单修复。 I am returning a total calculation, price * quantity, between the server and the client. 我正在返回服务器和客户端之间的总计算量,价格*数量。 However, I am receiving a java.net.SocketException: Connection Reset . 但是,我收到了java.net.SocketException: Connection Reset I have inserted a ComputerServer class w/class HandleAClient , ComputerClient class and Computer class. 我已插入ComputerServer类W /类HandleAClientComputerClient类和Computer类。 I welcome any help. 我欢迎任何帮助。 Thank you! 谢谢!

import java.io.*;
import java.util.*;
import java.net.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;

public class ComputerServer 
{
    public static void main(String args[])
    {
        ServerSocket serverSocket;
        Socket connection;

        ObjectInputStream input;
        ObjectOutputStream output;

        Computer c = null;

        Object obj;

        double totalCharge;

        try
        {
            serverSocket = new ServerSocket(8000);
            System.out.println("Waiting for Client");

            int clientNo = 1;

            ExecutorService threadExecutor = Executors.newCachedThreadPool();

            while(true)//runs indefinitely
            {
                connection = serverSocket.accept();

                input = new ObjectInputStream(connection.getInputStream());
                output = new ObjectOutputStream(connection.getOutputStream());

                obj = input.readObject();

                System.out.println("Object Received from client:\n"+obj);

                if(obj instanceof Computer)
                {
                    totalCharge = ((Computer)obj).getPrice()*((Computer)obj).getQuantity();

                    HandleAClient thread = new HandleAClient(connection, clientNo, totalCharge);

                    threadExecutor.execute(thread);

                    output.writeObject(totalCharge);
                    output.flush();
                }





                clientNo++;
            }

        }
        catch(ClassNotFoundException cnfe)
        {
            cnfe.printStackTrace();
        }
        catch(IOException ioe)
        {
            ioe.printStackTrace();
        }

    }//end of main
}

class HandleAClient implements Runnable
{
    //**SHOULD i do object...
    //Scanner input;
    //Formatter output;
    Object obj;

    ObjectOutputStream output;
    ObjectInputStream input;

    Socket connection;
    ServerSocket serverSocket;

    int clientNo;

    //variables for calculation
    //variables for calculation
    double price;
    double totalCharge;


    public HandleAClient(Socket connection, int clientNo, double totalCharge)
    {
        this.connection = connection;
        this.clientNo = clientNo;
        this.totalCharge = totalCharge;
    }

    public void run()
    {
        //ArrayList<Computer> cList = new ArrayList<Computer>();

        try
        {


            input = new ObjectInputStream(connection.getInputStream());
            output = new ObjectOutputStream(connection.getOutputStream());


            /*while(input.hasNext())
            {
                //variable = input.next....
                //print out calculation
                price = input.nextDouble();
                System.out.println("Price received from client:\t"+clientNo+"is"+price);

                //DO CALCULATION, STORE IT

                for(Computer c: cList)//**TRYING a for loop
                {
                    totalCharge = ((Computer)c).getPrice() * ((Computer)c).getQuantity();

                    output.format("%.2f\n", totalCharge);

                    //output.flush();
                }
            //}*/

            System.out.println("TotalCharge"+totalCharge);
            System.out.println("Thread"+"\t"+clientNo+"\t"+"ended");
        }
        catch(IOException ioe)
        {
            ioe.printStackTrace();
        }
    }
}

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

public class ComputerClient 
{
    public static void main(String args[])
    {
        Socket connection;

        ObjectOutputStream output;
        ObjectInputStream input;

        Object obj;

        Computer c = new Computer("Asus",1189.99,4);

        try
        {
            connection = new Socket("localhost",8000);

            output = new ObjectOutputStream(connection.getOutputStream());
            input = new ObjectInputStream(connection.getInputStream());

            output.writeObject(c);
            output.flush();

            //read back:

            obj=(Object)input.readObject();

            System.out.println(obj.toString());
        }
        catch(ClassNotFoundException cnfe)
        {
            cnfe.printStackTrace();
        }
        catch(IOException ioe)
        {
            ioe.printStackTrace();
        }
    }
}
    import java.io.Serializable;

public class Computer implements Serializable 
{
    private String brand;
    private double price;
    private int quantity;

    public Computer()
    {
        setBrand("");
        setPrice(0.0);
        setQuantity(0);
    }

    public Computer(String b, double p, int q)
    {
        setBrand(b);
        setPrice(p);
        setQuantity(q);
    }

    public String getBrand()
    {
        return brand;
    }

    public double getPrice()
    {
        return price;
    }

    public int getQuantity()
    {
        return quantity;
    }

    public void setBrand(String b)
    {
        brand = b;
    }

    public void setPrice(double p)
    {
        price = p;
    }

    public void setQuantity(int q)
    {
        quantity = q;
    }

    public String toString()
    {
        return("Brand: "+brand+"\t"+"Price: "+price+"\t"+"Quantity: "+quantity);
    }
}

'Connection reset' usually means you have written to a connection that had already been closed by the peer. “连接重置”通常意味着您已写入已被同级关闭的连接。 In other words, an application protocol error. 换句话说,应用程序协议错误。 You've written something that the peer didn't read. 您写的东西是同行没有读过的。 The next I/O operation, or a subsequent one depending on buffering, will get 'connection reset'. 下一个I / O操作或后续的I / O操作(取决于缓冲)将变为“连接重置”。

In this case the server is writing totalCharge and initializing two ObjectOutputStreams , which both write headers to the stream. 在这种情况下,服务器正在写入totalCharge并初始化两个ObjectOutputStreams ,这两个对象都将标头写入流中。 The client is only creating one ObjectInputStream, which reads one header, and reads one object, then closes the connection. 客户端仅创建一个ObjectInputStream,该对象读取一个标头,然后读取一个对象,然后关闭连接。 So the other header is written nowhere and causes the exception. 因此,其他标头未写入任何位置,并导致异常。

You can't do this. 你做不到 You can't use multiple ObjectOutputStreams on the same socket, at least not without special care that isn't evident here. 您不能在同一套接字上使用多个ObjectOutputStreams ,至少在没有特别注意的情况下不能这样,这在这里并不明显。 You also shouldn't be doing any I/O whatsoever in the accept loop. 您也不应在accept循环中进行任何I / O操作。 Move all the client processing to the HandleAClient class, which is what it's for after all, and don't do anything in the accept loop except accept connections and start threads for them. 将所有客户端处理移至HandleAClient类,这毕竟是要处理的类,并且在accept循环中不执行任何操作,除非接受连接并为其启动线程。

Also neither your server nor your client is closing the connection. 另外,您的服务器和客户端都没有关闭连接。 The server is just leaking sockets, and the client is just exiting. 服务器只是泄漏套接字,而客户端只是退出。 The operating system is closing it for you in the client case, but it's poor practice. 在客户端的情况下,操作系统会为您关闭它,但这是不明智的做法。 Close your connections. 关闭您的连接。 In this case you should close the ObjectOutputStream. 在这种情况下,您应该关闭ObjectOutputStream.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM