简体   繁体   中英

Sockets - Server getting stuck on in.readLine() - Java

I've recently been playing around with Sockets in Java but I came across a problem. The server get's stuck in the Server readLine(); I have no clue what is going on, if anyone can help that would be great. I know that the problem is not that readLine() only returns when there is a new line character, but I am using println() not just print().

Here is my current code:

Server Class:

package packets.sidedcomputer;

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

import packets.Packet;
import packets.data.PacketData;
import packets.info.ClientInfo;
import packets.reciever.PacketReciever;
import packets.sender.PacketSender;
import packets.side.Side;

public class Server extends SidedComputer
{
    volatile boolean finished = false;

    public ServerSocket serverSocket;

    public volatile List<ClientInfo> clients = new ArrayList<ClientInfo>();

    public void stopServer()
    {
        finished = true;
    }

    public Server()
    {
        try 
        {
            serverSocket = new ServerSocket(10501);
        } 
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public void run()
    {
        try 
        {
            while (!finished)
            {
                Socket clientSocket = serverSocket.accept();  

                if(clientSocket != null)
                {
                    ClientInfo clientInfo = new ClientInfo(clientSocket);

                    this.clients.add(clientInfo);

                    BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

                    String dataString = in.readLine();

                    while(dataString != null && !dataString.equals(""))
                    {
                        PacketReciever packetReciever = new PacketReciever();

                        PacketData packetData = new PacketData();

                        packetData.decodeInto(dataString);

                        Packet packet = packetReciever.recievePacket(packetData, packetData.packetID, getSide(), clientSocket.getLocalAddress().getHostAddress().toString(), clientSocket.getLocalPort() + "");

                        PacketSender packetSender = new PacketSender();

                        for (ClientInfo client : this.clients)
                        {
                            PrintWriter out = new PrintWriter(client.socket.getOutputStream(), true);
                            packetSender.sendPacketToClient(packet, out);
                        }

                        dataString = in.readLine();
                    }

                    serverSocket.close();
                }
            }
        } 
        catch (Exception e) 
        {
            e.printStackTrace();
            System.exit(1);
        }
    }

    @Override
    public Side getSide() 
    {
        return Side.SERVER;
    }
}

My Client Class:

package packets.sidedcomputer;

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

import packets.MessagePacket;
import packets.sender.PacketSender;
import packets.side.Side;

public class Client extends SidedComputer
{
    volatile boolean finished = false;

    volatile String username;

    volatile Server server;

    public Socket clientSocket;

    public ClientReciever reciever;

    public Client(Server server, String username) throws UnknownHostException, IOException
    {
        this.username = username;
        this.server = server;
        this.reciever = new ClientReciever(this);
    }

    public void stopClient()
    {
        finished = true;
    }

    @Override
    public void run()
    {
        Scanner scanner = new Scanner(System.in);

        reciever.start();

        while(!finished)
        {
            try 
            {
                this.clientSocket = new Socket("192.168.1.25", 10501);

                String line;

                while((line = scanner.nextLine()) != null)
                {     
                    PacketSender sender = new PacketSender();

                    sender.sendPacket(new MessagePacket(line, username), clientSocket.getLocalAddress().getHostAddress().toString(), "" + clientSocket.getPort());
                }
            }
            catch (Exception e) 
            {
                e.printStackTrace();
            }

        }

        scanner.close();
    }

    @Override
    public Side getSide() 
    {
        return Side.CLIENT;
    }
}

My packet sender class:

package packets.sender;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;

import packets.Packet;
import packets.data.PacketData;

public class PacketSender implements IPacketSender
{
    @Override
    public void sendPacket(Packet packet, String host, String port)
    {
        if(packet.getDefualtID() == 0)
        {
            PacketData packetData = new PacketData(packet.getDefualtID());

            packet.writeData(packetData);

            String data = packetData.encodeIntoString();

            sendData(host, port, data);
        }
    }

    protected void sendData(String hostName, String port, String data)
    {
        try 
        {

            try 
            (
                Socket socket = new Socket(hostName, Integer.parseInt(port));
                PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            ) 
            {
                out.println(data);
            } 
            catch (UnknownHostException e)
            {
                System.err.println("Don't know about host " + hostName);
                System.exit(1);
            } 
            catch (IOException e) 
            {
                System.err.println("Couldn't get I/O for the connection to " + hostName);
                System.exit(1);
            } 
        }
        catch (Exception e) 
        {
            e.printStackTrace();
        }
    }

    public void sendPacketToClient(Packet packet, PrintWriter out)
    {
        PacketData packetData = new PacketData(packet.getDefualtID());

        packet.writeData(packetData);

        String data = packetData.encodeIntoString();

        out.println(data);
    }
}

Here's what's happening

From your client:

this.clientSocket = new Socket("192.168.1.25", 10501);

When this line runs, the server will be woken up from the accept line. And block again at readLine()

Meanwhile, your client, goes through your PacketSender. What does your PacketSender do?

Socket socket = new Socket(hostName, Integer.parseInt(port));

This opens a new connection! So your Client is waiting for the server to accept a connection. And the server is waiting for the client to send a message! You arrive at a deadlock.

Here's how to fix it

remove the following line.

this.clientSocket = new Socket("192.168.1.25", 10501);

then pass the host address and port manually into your PacketSender.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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