I am building a client-server application using threading, but for some reason the BufferedWriter won't send the data out to the client through the socket.
I also get a Socket Exception: Connection Reset after running the client.
What am i missing?
Server:
public class Servernew {
protected String username;
protected ServerSocket serverSocket;
protected static LinkedList<ClientThreadNew> clients;
public static LinkedList<ClientThreadNew> getClients() {
return clients;
}
public Servernew(int port) {
try {
serverSocket = new ServerSocket(port);
clients = new LinkedList<ClientThreadNew>();
System.out.println("Server is now running on port " + port);
while (true) {
Socket clientSocket = serverSocket.accept();
ClientThreadNew clientThread = new ClientThreadNew(
clientSocket, username);
clients.addLast(clientThread);
clientThread.start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
new Servernew(4444);
}
}
ClientThread:
public class ClientThreadNew extends Thread implements Runnable {
protected String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
protected Socket clientSocket;
protected BufferedReader inFromClientB;
protected BufferedWriter outToClient;
public ClientThreadNew(Socket clientSocket, String username)
throws IOException {
this.clientSocket = clientSocket;
this.username = username;
inFromClientB = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
outToClient = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
}
public void run() {
try {
while (true) {
String incomingMessage = inFromClientB.readLine();
if (incomingMessage != null) {
setUsername(incomingMessage);
outToClient.write("hii");
outToClient.newLine();
outToClient.flush();
}
}
} catch (IOException e) {
System.out.print(e);
}
}
}
ClientTest:
public class ClientTesst {
private static Socket socket;
private static BufferedWriter outToServer;
private String hostname;
private int portnum;
private static BufferedReader inFromServer;
public ClientTesst(String hostname, int portnum) throws IOException {
this.hostname = hostname;
this.portnum = portnum;
}
public void connect() throws UnknownHostException, IOException {
socket = new Socket(hostname, portnum);
System.out.println("Connection Established");
}
public String listUsers() throws IOException {
inFromServer = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
String listOfUsers = inFromServer.readLine().toString();
return (listOfUsers);
}
public void sendMessage(String Msg) throws IOException {
outToServer = new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream()));
outToServer.write(Msg);
outToServer.newLine();
outToServer.flush();
}
public static void main(String[] args) throws Exception {
ClientTesst x = new ClientTesst("localhost", 4444);
x.connect();
x.sendMessage("client x");
ClientTesst y = new ClientTesst("localhost", 4444);
y.connect();
y.sendMessage("client y");
y.listUsers();
}
}
In your ClientTesst class you have this:
private static Socket socket;
private static BufferedReader inFromServer;
private static BufferedWriter outToServer;
and since all this variables are static it means that both clients x and y will use the same socket, outToServer and inFromServer.
Make this variables as instance variables (by remove the static) so that each instance of ClientTesst will have its on socket and streams.
The following works -
class ClientThreadNew extends Thread implements Runnable {
protected String username;
protected Socket clientSocket;
protected BufferedReader inFromClientB;
protected BufferedWriter outToClient;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public ClientThreadNew(Socket clientSocket, String username) throws IOException {
this.clientSocket = clientSocket;
this.username = username;
}
public void run() {
try {
outToClient = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
inFromClientB = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String incomingMessage, outgoingMessage;
while ((incomingMessage = inFromClientB.readLine()) != null) {
setUsername(incomingMessage);
System.out.println("From client: " + incomingMessage);
outgoingMessage = "hii";
Thread.sleep(2000);
outToClient.write(outgoingMessage);
outToClient.newLine();
outToClient.flush();
System.out.println("From server: " + outgoingMessage);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class ClientTest {
private Socket socket;
private BufferedReader inFromServer;
private BufferedWriter outToServer;
private String hostname;
private int portnum;
public ClientTest(String hostname, int portnum) throws IOException {
this.hostname = hostname;
this.portnum = portnum;
}
public void connect() throws IOException {
socket = new Socket(hostname, portnum);
outToServer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
inFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("Connection Established");
}
public String listUsers() throws IOException {
return inFromServer.readLine();
}
public void sendMessage(String Msg) throws IOException {
outToServer.write(Msg);
outToServer.newLine();
outToServer.flush();
}
public static void main(String[] args) throws Exception {
ClientTest x = new ClientTest("localhost", 4444);
x.connect();
x.sendMessage("client x");
String messageFromServer;
while ((messageFromServer = x.listUsers()) != null) {
System.out.println("From server: " + messageFromServer);
Thread.sleep(2000);
x.sendMessage("client x");
System.out.println("From client: client x");
}
}
}
Related
This is code provided to me for a class. I am trying trying to fix a connection problem between the client and server. Even when both are started they do not connect.
This is for a Java based game of Battleship that will allow two users on separate devices to play one another. I'm not sure why the two do not connect and even the debugger has not been much help in directing me to the problem.
public class GameClient
{
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public void openConnection(String ip, int port)
{
try
{
clientSocket = new Socket(ip, port);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}
catch (Exception e)
{
System.out.println("Error opening client socket");
}
}
public String sendMessage(String msg)
{
String resp = "";
try
{
out.println(msg);
resp = in.readLine();
}
catch (Exception e)
{
System.out.println("Error sending message from Client");
}
return resp;
}
public void stop()
{
try
{
in.close();
out.close();
clientSocket.close();
}
catch (Exception e)
{
System.out.println("Error stopping client");
}
}
public static void main(String[] args)
{
GameClient client = new GameClient();
client.openConnection("10.7.232.200", 3333);
String response = client.sendMessage("1,2");
System.out.println(response);
client.stop();
}
}
public class GameServer
{
private ServerSocket serverSocket;
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public void start(int port)
{
try
{
serverSocket = new ServerSocket(port);
clientSocket = serverSocket.accept();
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String move = in.readLine();
System.out.println(move);
out.println("6,1");
}
catch (Exception e)
{
System.out.println("Socket opening error");
}
}
public void stop()
{
try
{
in.close();
out.close();
clientSocket.close();
serverSocket.close();
}
catch (Exception e)
{
System.out.println("Error closing sockets");
}
}
public static void main(String [] args)
{
GameServer server = new GameServer();
server.start(3333);
server.stop();
}
}
public class PlayBattleship
{
public static void main(String[] args)
{
GameClient client = new GameClient();
client.openConnection("10.7.232.200", 3333);
//System.out.println(response);
BattleshipGame game = new BattleshipGame();
while (!game.checkEndgame())
{
game.getGuess(client);
}
client.stop();
}
}
The client and server should connect and stay connected till the game has reached completion
EDIT: I have thoroughly read the API documentation but still cannot understand the problem.
The Server in your code isn't waiting for the incoming requests, it only serves a single incoming request and then kills itself due to the nature of the main method which starts it.
You need to have the server wait for the requests and do not die. Check the code snippet below to understand the logic.
Plus, always try to throw the exceptions if you can't do anything meaningful with it within the method it is caught in. In your code the main method of the server will anyway execute even if there is an exception caught in the start method
public class GameServer {
private ServerSocket serverSocket;
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public ServerSocket start(int port) throws IOException {
serverSocket = new ServerSocket(port);
return serverSocket;
}
public void stop() throws IOException {
in.close();
out.close();
clientSocket.close();
serverSocket.close();
}
// This method accepts and serves the incoming requests
public void acceptConnection(ServerSocket serverSocket) throws IOException {
clientSocket = serverSocket.accept();
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String move = in.readLine();
System.out.println(move);
out.println("6,1");
}
public static void main(String[] args) throws IOException {
GameServer server = new GameServer();
ServerSocket serverSocket = server.start(3333);
System.out.println("Server Started");
// The effective change you need to make
// Loop through the incoming requests
while(true) {
server.acceptConnection(serverSocket);
}
}
}
public class GameClient {
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public void openConnection(String ip, int port) throws IOException {
clientSocket = new Socket(ip, port);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}
public String sendMessage(String msg) throws IOException {
String resp = "";
out.println(msg);
resp = in.readLine();
return resp;
}
public void stop() throws IOException {
in.close();
out.close();
clientSocket.close();
}
public static void main(String[] args) throws IOException {
GameClient client = new GameClient();
client.openConnection("10.7.232.200", 3333);
String response = client.sendMessage("1,2");
System.out.println(response);
client.stop();
}
}
I have written a simple multithreaded Server on which the two Clients can send Messages to the Server an the Server a Message to all the Clients at once. But I can't get it to work as intended.
I already tried it by putting a List of all PrintWriters in the Server class and then print the Message through each PrintWriter but this didn't work either.
public class Client
{
private static final String IP = "10.59.0.188";
private Socket clientSocket;
private PrintWriter toServer;
private BufferedReader fromServer;
private BufferedReader input;
private String serverMessage;
private String clientMessage;
private String name;
public static void main(String[] args) {
try {
new Client();
} catch (Exception e) {
System.err.println(e);
}
}
public Client() throws IOException {
input = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Name: ");
name = input.readLine();
openConnection();
toServer.println(name);
while (true) {
clientMessage = input.readLine();
toServer.println(clientMessage);
}
//closeConnection();
}
private void openConnection() throws IOException{
clientSocket = new Socket(IP, 6666);
toServer = new PrintWriter(clientSocket.getOutputStream(), true);
fromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}
}
public class Server {
private ServerSocket serverSocket;
private BufferedReader input;
private Vector<ClientProcess> processList;
private int clientCount = 0;
private String serverMessage;
public static void main(String[] args) {
try {
new Server();
} catch (Exception e) {
System.err.println(e);
}
}
public Server() throws IOException {
startServer();
while (clientCount < 2) {
waitForNewClient();
}
for (ClientProcess clientProcess : processList) {
clientProcess.start();
System.out.println("Clientprocess started");
}
}
private void startServer() throws IOException {
processList = new Vector<>();
input = new BufferedReader(new InputStreamReader(System.in));
serverSocket = new ServerSocket(6666);
System.out.println("Server online");
}
private void waitForNewClient() throws IOException {
System.out.println("Waitin' for new Client...");
Socket clientSocket = serverSocket.accept();
ClientProcess clientProcess = new ClientProcess(clientSocket);
processList.add(clientProcess);
clientCount++;
}
}
public class ClientProcess extends Thread {
private Socket clientSocket;
private PrintWriter toClient;
private BufferedReader fromClient;
private String clientMessage;
private String serverMessage;
private String name;
private BufferedReader input;
public ClientProcess(Socket clientSocket) {
this.clientSocket = clientSocket;
input = new BufferedReader(new InputStreamReader(System.in));
}
#Override
public void run() {
try {
openClientConnection();
name = fromClient.readLine();
do {
clientMessage = fromClient.readLine();
System.out.println(name + ": " + clientMessage);
} while (true);
//closeClientConnection();
} catch (IOException e) {
System.err.println(e);
}
}
private void openClientConnection() throws IOException {
toClient = new PrintWriter(clientSocket.getOutputStream());
fromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
serverMessage = "ServerMessageTest00";
toClient.println(serverMessage);
System.out.println("Client Connection Online");
}
}
In the ClientProcess you create a new PrintWriter.
From the javadoc:
Creates a new PrintWriter, without automatic line flushing, from anexisting OutputStream.
This means your toClient.println(...); is wrote to the server's output buffer but will not be send to the client because you miss the toClient.flush().
This question already has an answer here:
ObjectInputStream(socket.getInputStream()); does not work
(1 answer)
Closed 7 years ago.
I'm doing a simple echo chat and server, but methods send and receive in class Connection don't work with ObjectInputStream and ObjectOutputStream, but with PrintWriter and BufferedReader work fine.
Now I'm trying to understand the serialization using sockets, help me to understand why this code does not work:
Client
public class Client {
private Connection connection;
private String getServerAddress() {
return "localhost";
}
private int getServerPort() {
return 4444;
}
public void run() {
BufferedReader bis = new BufferedReader(new InputStreamReader(System.in));
try {
connection = new Connection(new Socket(getServerAddress(), getServerPort()));
SocketThread socketThread = new SocketThread();
socketThread.setDaemon(true);
socketThread.start();
while (true) {
String text = bis.readLine();
if (text.equalsIgnoreCase("exit"))
break;
connection.send(text);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Client client = new Client();
client.run();
}
public class SocketThread extends Thread {
#Override
public void run() {
try {
while (true) {
String message = connection.receive();
System.out.println(message);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Connection
public class Connection implements Closeable {
private final Socket socket;
private final ObjectInputStream in;
private final ObjectOutputStream out;
public Connection(Socket socket) throws Exception {
this.socket = socket;
this.in = new ObjectInputStream(socket.getInputStream());
this.out = new ObjectOutputStream(socket.getOutputStream());
}
public void send(String message) throws Exception {
out.writeObject(message);
}
public String receive() throws Exception {
return (String) in.readObject();
}
#Override
public void close() throws IOException {
in.close();
out.close();
socket.close();
}
}
Server
public class Server {
public static void main(String[] args) {
int port = 4444;
try (ServerSocket serverSocket = new ServerSocket(port)) {
while (true) {
Socket socket = serverSocket.accept();
new Handler(socket).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static class Handler extends Thread {
private Socket socket;
public Handler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try (Connection connection = new Connection(socket)) {
while (true) {
String message = connection.receive();
if (message.equals("exit"))
break;
System.out.println(message);
connection.send("Echo: " + message);
}
} catch (Exception e) {
}
}
}
}
This is because ObjectInputStream blocks trying to read the stream header written by an ObjectOutputStream in its constructor, and you are creating both of your input streams before the output streams. You can solve this by switching the order that you create the object streams in:
this.out = new ObjectOutputStream(socket.getOutputStream());
this.in = new ObjectInputStream(socket.getInputStream());
The javadoc for the ObjectOutputStream constructor also notes that you might want to flush the stream after creating it to ensure the header is sent.
A client connects to the Server, the server sends to the client 1 message and the client must wait for another message. While client waiting in while(true) loop it loads the CPU to 50%. I try to do this as simple I can to learn how it works.
P.S. All catch() already hiden to minimize code here.
Client:
public class SocketClient
{
String host;
int port;
static Socket connection;
BufferedReader bfr;
public SocketClient(String host, int port)
{
this.port = port;
this.host = host;
}
public void connect() throws UnknownHostException, IOException, Exception
{
connection = new Socket(new String(host), port);
System.out.println("Client is ready.");
bfr = new BufferedReader(new InputStreamReader(connection.getInputStream()));
}
public void readInput() throws IOException
{
String input;
if(input = bfr.readLine()) != null)
{
System.out.println(input);
}
}
public static void main(String[] args) throws UnknownHostException, IOException, Exception
{
SocketClient socketClient = new SocketClient("localhost", 19999);
try {
socketClient.connect();
try
{
while(true)
{
socketClient.readInput();
}
}
}
}
}
Server:
public class MultipleSocketServer implements Runnable {
private Socket connection;
private String TimeStamp;
private int ID;
static PrintWriter writer;
private static File file;
public static void main(String[] args)
throws FileNotFoundException, UnsupportedEncodingException
{
int port = 19999;
int count = 0;
file = new File("E:/test.txt");
writer = new PrintWriter(file, "UTF-8");
try
{
ServerSocket socket = new ServerSocket(port);
System.out.println("MultipleSocketServer Initialized");
while (true)
{
Socket connection = socket.accept();
Runnable runnable = new MultipleSocketServer(connection, ++count);
Thread thread = new Thread(runnable);
thread.start();
}
}
}
MultipleSocketServer(Socket s, int i) {
this.connection = s;
this.ID = i;
}
public void run() {
try {
System.out.println("Connected: " + connection.getLocalSocketAddress() + " at port " + connection.getPort());
writer.println(ID + ": " + connection.getLocalSocketAddress() + " at port " + connection.getPort());
writer.flush();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));
writer.write("MultipleSocketServer repsonded at " + new java.util.Date().toString());
writer.write("\n");
writer.flush();
}
finally {
try {
connection.close();
}
}
}
}
Analysis
It seems the server side closes connection after sending the data.
The client side has the following infinite loop:
while (true)
{
socketClient.readInput();
}
The loop can cause the CPU consumption: the method bfr.readLine() method call will return null immediately after the connection is closed.
Solution
Please consider changing the loop of the client side to read until "the end-of-connection":
String input;
while ((input = bfr.readLine()) != null) {
System.out.println(input);
}
I'm writing my first socket project and I have a problem. When the client sends a String to the server, the server can't get this message.
public class ClientActivity {
public static final String serverIP = "127.0.0.1";
private Socket clientSocket = null;
private static BufferedOutputStream out = null;
public static void main(String[] args) throws IOException {
ClientActivity me = new ClientActivity();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
out.write("Some string");
}
public ClientActivity() throws UnknownHostException, IOException {
clientSocket = new Socket(serverIP, serverPort);
out = new BufferedOutputStream(clientSocket.getOutputStream());
}
}
Here is the server's code:
public class DataTransferServer {
private ServerSocket serverSocket;
private ArrayList<DataReaderThread> workingThreads;
private Boolean isListening;
private Thread listener;
public static void main(String[] args) throws IOException {
new DataTransferServer(IProtocolConstants.SERVER_PORT).startServer(); // FIXME
}
public DataTransferServer (int port) throws IOException {
System.out.println("Launch");
serverSocket = new ServerSocket(port);
workingThreads = new ArrayList<DataReaderThread>();
isListening = true;
listener = new ConnectionListener();
}
public void startServer() throws IOException {
listener.start();
}
private class ConnectionListener extends Thread {
#Override
public void run() {
DataReaderThread newThread = null;
while (isListening) {
try {
newThread = new DataReaderThread(serverSocket.accept(), DataTransferServer.this);
newThread.start();
workingThreads.add(newThread);
System.out.println("! thread started");
} catch (IOException e) {
e.printStackTrace(); // FIXME
}
}
if (newThread != null) {
newThread.interrupt();
newThread = null;
}
}
}
}
And here is the listener:
public class DataReaderThread extends Thread {
private Socket socket = null;
private BufferedInputStream in = null;
private byte[] stuffBytes = null;
public DataReaderThread(Socket socket) throws IOException {
super("DataReaderThread");
this.socket = socket;
in = new BufferedInputStream(socket.getInputStream());
stuffBytes = new byte[10];
}
public void run() {
try {
while (in.read(stuffBytes, 0, stuffBytes.length) != -1) {
System.out.println("Received data:" + new String(stuffBytes));
}
in.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public Socket getSocket() {
return socket;
}
I guess the BufferedOutputStream out does not send a TCP packet until the buffer is full.
Try calling flush after write to send the data immediately:
out.write("Some string");
out.flush();
You may also consider using the PrintWriter class instead, which has an autoflush mechanism.
-1 Compile your code before posting...
public class ClientActivity {
public void write(String data) {
out.write(data.getBytes())
out.flush()
}
public static final String serverIP = "127.0.0.1";
private Socket clientSocket = null;
private BufferedOutputStream out = null;
public static void main(String[] args) throws IOException {
ClientActivity me = new ClientActivity();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
me.write("Some string");
}
public ClientActivity() throws UnknownHostException, IOException {
clientSocket = new Socket(serverIP, serverPort);
out = new BufferedOutputStream(clientSocket.getOutputStream());
}
}