I need to test some client/server application using JUnit and I'm having trouble testing the connection of a client to the server. It seems that the test hangs at the "Socket clientSocket = serverSocket.accept()" line in the server class, and it's not letting me connect a new client.
Here's the JUnit class:
#Test
public void testNetServerComm_1() throws Exception {
server = new NetServerComm();
assertNotNull(server);
}
#Test
public void testAddMessageToQueue_1() throws Exception {
NetServerComm fixture = new NetServerComm();
NetServerSideMessage msg = new NetServerSideMessage(birdsong.comm.ServerSideMessage.Type.BIRDSONG_MESSAGE, "",
"");
fixture.addMessageToQueue(msg);
assertEquals(1, fixture.getMsgQueueSize());
}
#Test
public void testClientIsConnected_1() throws Exception {
NetServerComm fixture = new NetServerComm();
fixture.start();
//test doesn't go further that this..
String nickname = "john";
new NetClientComm().connect("127.0.0.1", nickname);
boolean result = fixture.isClientConnected(nickname);
assertTrue(result);
}
Client Class:
//connects to the server
#Override
public void connect(String host, String nickname) {
try {
clientNickname = nickname;
System.out.println("Address= " + host + " and NickName = " + nickname);
socket = new Socket(host, NetServerComm.PORTO); //8080
System.out.println("Socket = " + socket);
serverMsg = new NetServerSideMessage(ServerSideMessage.Type.CLIENT_CONNECTED, null, clientNickname);
out = new ObjectOutputStream(socket.getOutputStream());
out.writeObject(serverMsg);
isConnected = true;
messageHandler = new Thread(new MessageHandler(socket));
messageHandler.start();
} catch (IOException e) {
System.out.println("Failed connecting to the server.");
e.printStackTrace();
}
}
Server Class:
//starts the server
#Override
public void start() {
try {
serverSocket = new ServerSocket(PORTO); //8080
System.out.println("Servidor is online: " + serverSocket);
try {
while (true) {
Socket clientSocket = serverSocket.accept();
//test hangs at the method above^^^
checkNewClient(clientSocket);
if (nameCheck == true)
new Thread(new ClientHandler(clientSocket)).start();
}
} finally {
System.out.println("Closing the server..");
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
It looks like you start() method is getting executed by the same Thread as the test, so it blocks there (at the accept() part). Could you try to have this method executed by a new Thread instead ? – Berger
That seems to have done the job :) – JDev
Related
I've been trying to make the code below to have multiple clients communicate with the same server.
Currently, it works one client at a time with the server but it seems to be that when the second client opens, code stops at new ObjectInputStream(connection.getInputStream()); in the Class 3 (client) - see below.
I've tried making the inputstream object transient to be shared in different threads but it didn't work, nor with making runClient method synchronized.
If I were to implement Serializable in the client class using serialVersionUID, how can I make multithreading work with the same server or is there any better way..?
Class 1 - server main
public class EchoServer {
private ServerSocket server;
private int portNum;
public static final int DEFAULT_PORT = 8081;
public EchoServer(int portNum) {
this.portNum = portNum;
}
public void runServer() {
System.out.println("Echo Server started...");
try {
server = new ServerSocket(portNum);
Socket connection = server.accept();
new Thread(new ClientHandler(connection)).run();
} catch(IOException ex) {
System.err.println("Error encountered! Port is likely already in use! Exiting program...");
ex.printStackTrace();
}
}
public static void main(String[] args) {
if (args.length > 0) {
(new EchoServer(Integer.parseInt(args[0]))).runServer();
} else {
(new EchoServer(DEFAULT_PORT)).runServer();
}
}
}
Class 2
public class ClientHandler implements Runnable {
private ObjectOutputStream output;
private ObjectInputStream input;
private String message;
/** Integer to hold the message number. */
private int messagenum;
private Socket connection;
public ClientHandler(Socket connection) {
this.connection = connection;
}
#Override
public void run() {
do{
handleRequest();
} while (true);
}
public void handleRequest() {
try {
output = new ObjectOutputStream(this.connection.getOutputStream());
input = new ObjectInputStream(this.connection.getInputStream());
do {
try {
message = (String) input.readObject();
System.out.println(messagenum +" Output> " +message);
} catch (EOFException | SocketException e) {
message = null;
}
if (message != null) {
output.writeObject(messagenum +" FromServer> " +message);
output.flush();
++messagenum;
}
} while (message != null);
input.close();
output.close();
this.connection.close();
} catch (IOException | ClassNotFoundException ex) {
System.err.println("Error encountered! Exiting program...");
ex.printStackTrace();
}
}
}
Class 3 - client main
public class EchoClient implements Serializable {
private static final long serialVersionUID = 1L;
private Socket connection;
private ObjectOutputStream output;
private transient ObjectInputStream input;
private String message = "";
private static String serverName;
public static final String DEFAULT_SERVER_NAME = "localhost";
private static int portNum;
BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
public EchoClient(String serverName, int portNum) {
this.serverName = serverName;
this.portNum = portNum;
}
public synchronized void runClient() {
try {
connection = new Socket(InetAddress.getByName(serverName), portNum);
output = new ObjectOutputStream(connection.getOutputStream());
input = new ObjectInputStream(connection.getInputStream());
do {
System.out.print("Input> ");
message = keyboard.readLine();
if (message != null){
output.writeObject(message);
output.flush();
message = (String) input.readObject();
System.out.println(message);
}
} while (message != null);
input.close();
output.close();
connection.close();
} catch (IOException ioException) {
ioException.printStackTrace();
} catch (ClassNotFoundException exception) {
exception.printStackTrace();
}
}
public static void main(String[] args) {
switch (args.length) {
case 2:
(new EchoClient(args[0], Integer.parseInt(args[1]))).runClient();
break;
case 1:
(new EchoClient(DEFAULT_SERVER_NAME, Integer.parseInt(args[0]))).runClient();
break;
default:
(new EchoClient(DEFAULT_SERVER_NAME, server.EchoServer.DEFAULT_PORT)).runClient();
}
}
}
Call server.accept() in the loop to accept multiple client connections as mentioned in the other answers. Start a new thread with the Thread.start method instead of Thread.run- What's the difference between Thread start() and Runnable run().
volatile boolean isRunning = true;
public void runServer() {
System.out.println("Echo Server started...");
try {
server = new ServerSocket(portNum);
while(isRunning) {
Socket connection = server.accept();
new Thread(new ClientHandler(connection)).start();
}
} catch(IOException ex) {
System.err.println("Error encountered! Port is likely already in use! Exiting program...");
ex.printStackTrace();
}
}
run server needs to wait for connections in a loop otherwise it will connect once and that is it. It needs to close its connections too. Clean up its threads. that's just in server main. I'm pretty sure this is a duplicate. So keep on researching
As said by efekctive, you need your server.accept() in a loop, else it will accept the first client and exit the program. So put these two lines in runServer() in a loop like this:
boolean isRunning = true;
while(isRunning){
Socket connection = server.accept();
new Thread(new ClientHandler(connection)).run();
}
I have been working with TCP server/client stuff for a while. I am actully good at UDP programming when it comes to connecting more than one user that is multiple clients. I tried to do the same on a TCP server that i made using Threads but whenever the Thread gets to this piece of code
String reader = (String)in.readObject();
an error is generated and the thread stops executing the code but the thread still runs the program keeping it alive.
Anyway here is the entire source code :
public class TestServer implements Runnable {
private Thread run, streams, connect, receive, send;
private ServerSocket socket;
private Socket conn;
private ObjectInputStream in;
private ObjectOutputStream out;
private boolean running, incomingMessage = false;
private int port;
public TestServer(int port) throws IOException {
this.port = port;
socket = new ServerSocket(port);
console("Server stated on : " + InetAddress.getLocalHost() + " : " + port);
run = new Thread(this, "Run");
run.start();
}
public void run() {
running = true;
connect();
receive();
}
private void connect() {
connect = new Thread("Connect") {
public void run() {
while(running) {
try {
conn = socket.accept();
} catch (IOException e) {
e.printStackTrace();
}
console("You are now connected" + conn.getInetAddress().toString() + " : " + conn.getPort());
try {
setupStreams();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}; connect.start();
}
private void setupStreams() throws IOException {
streams = new Thread("Streams") {
public void run() {
try {
console("Setting up Streams");
out = new ObjectOutputStream(conn.getOutputStream());
out.flush();
in = new ObjectInputStream(conn.getInputStream());
console("Streams are now setup");
incomingMessage = true;
receive.start();
} catch(IOException e) {
e.printStackTrace();
}
}
}; streams.start();
}
private void receive() {
receive = new Thread("Receive") {
public void run() {
while(incomingMessage) {
String message = "";
try {
message = (String) in.readObject();
//This is the only flaw the program
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
console("Client : " + message);
}
}
};
}
private void console(String message) {
System.out.println(message);
}
public static void main(String[] args) {
try {
new TestServer(1234);
} catch (IOException e) {
e.printStackTrace();
}
}
}
FYI am not new to this. The error is caused because the server starts receiving packets even when there are no packets to be received. But because the thread forces it to receive it, i generates the error in the thread and dont know any other way to counter this. So please help. Thanks in Advance.
You shouldn't need 2 threads per connection. One thread is all that's required. After the connection is accepted, pass it to a worker thread to start reading. This can be done in a while loop in the worker thread.
Even though the socket's input stream can be read, the ObjectInputStream() class is more sensitive. If there is any error, its state is corrupted and it can't be used.
while (true) {
try {
Object input = in.readObject();
message = (String) input;
} catch (IOException e) {
e.printStackTrace();
break; //unrecoverable
} catch (ClassNotFoundException e) {
e.printStackTrace();
break; //unrecoverable
}
console("Client : " + message);
}
It's a better design to use a specific message protocol instead of sending serialized Java objects. For example if you are sending Strings like your sample, an InputStreamReader can be used to convert bytes to characters more easily and with less error handling.
These resources would be helpful to you:
https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html#later
Java - Listening to a socket with ObjectInputStream
ObjectInputStream(socket.getInputStream()); does not work
public class Main {
public static void main(String[] args) {
Server server = new Server(9008);
}
}
public class Server {
private ServerSocket server;
private Socket client;
public Server(int port) {
try {
// Create out server with our desired port
server = new ServerSocket(port);
// Server started, let the user know
System.out.println("Server started at port " + port + "...");
} catch (IOException e) {
// Unable to start server, print error
System.out.println("Unable to start server on port " + port + "...");
}
// Start our main server method
runServer();
}
public void runServer() {
while (true) {
try {
// Wait for new clients and accept them
client = server.accept();
// Let the user know - print
System.out.println("New user connected - " + client.getLocalAddress().getHostAddress());
// Start thread for our client
Thread clientThread = new Thread(new ClientConnection(client));
clientThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
So at this points everything is going fine, now inside my clientThread the problem starts
public class ClientConnection implements Runnable {
private Socket socket;
public ClientConnection(Socket client) {
// Set client socket
this.socket = client;
}
public void run() {
try {
// Read from our client input
BufferedReader readClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while ((line = readClient.readLine()) != null) {
System.out.println("Client says - " + readClient.readLine());
}
} catch(IOException e) {
}
}
}
Is there a better way to handle this?
My actual client
public class Main {
public static void main(String args[]) {
try {
Socket socket = new Socket("localhost", 9008);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
writer.write("Hello\n");
writer.flush();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I will get "Client says - null" displayed
UPDATE: The way to read in an InputStream/Reader is somethink like
while ((myString = readClient.readLine()) != null) {
System.out.println(myString);
}
this way the loop will exit when the connection is closed.
Also, move the try/catch outside the loop, or do some error control. If you get an exception, you do not want to just try get again in the loop.
UPDATE2: In case my comment was not clear enough, over your updated code do
String line;
while ((line = readClient.readLine()) != null) {
System.out.println("Client says - " + line);
}
Just one read per iteration, at the while, so the loop can exit if line is null (that means the connection has been closed).
I'm trying to make a simple ECHO server that can manage more client.
Server Class:
public class EchoServer {
protected int port ;
protected ServerSocket socket;
private Socket acceptedSocket;
public EchoServer(int port) throws IOException {
this.port = port;
socket = new ServerSocket(port);
}
public void start() throws AcceptingClientException {
while(!socket.isClosed()) {
try {
acceptedSocket = socket.accept();
}
catch (IOException e){
throw new AcceptingClientException();
}
ClientHandler ch = new ClientHandler(acceptedSocket);
ch.run();
}
}
}
Runnable client handler:
public class ClientHandler implements Runnable {
Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
PrintWriter From_Server = null;
BufferedReader To_Server = null;
String to_server_string = null;
try {
From_Server = new PrintWriter(socket.getOutputStream());
To_Server =
new BufferedReader(
new InputStreamReader( socket.getInputStream()));
System.out.println("Stream opened.\n");
while(true) {
if(To_Server.ready()){
System.out.println("Reading input line.\n");
to_server_string = To_Server.readLine();
if(to_server_string.equalsIgnoreCase("quit")) {
System.out.println("Connection closed on user request.\n");
From_Server.print("Bye :)\n");
From_Server.close();
To_Server.close();
socket.close();
}
else {
System.out.println(
"String '" +
to_server_string+"' is not 'quit', echoing.\n");
From_Server.print("ECHO: "+to_server_string+"\n");
System.out.println("String written on stream, flushing.\n");
From_Server.flush();
}
}
}
}
catch (IOException e) {
System.out.println("Stream error (connection closed?).\n");
}
}
}
Main Class
public static void main(String[] args) {
try {
EchoServer server= new EchoServer(9999);
server.start();
}
catch (IOException ex) {
System.out.println("Unable to start server (port is busy?)\n");
Logger.getLogger(SimpleServer.class.getName()).log(Level.SEVERE, null, ex);
}
catch (AcceptingClientException e){
System.out.println("Unable to accept client\n");
}
}
More than one client is able to connect to the server, but the ECHO will works only with one client at the time (if I close the connection with one client the server will start to handle another one automatically), but I can't understand why: when a client connects to the server, the associated socked created with server.accept() is passed to a new instance of a runnable client handler which is started with handler.run() and the server should go back on waiting in server.accept() (unless the ServerSocket is closed).
I'm assuming the issue should be with this method of the server class:
public void start() throws AcceptingClientException {
while(!socket.isClosed()) {
try {
acceptedSocket=socket.accept();
}
catch (IOException e){
throw new AcceptingClientException();
}
ClientHandler ch = new ClientHandler(acceptedSocket);
ch.run();
}
}
But I can't figure out what is wrong with it...what am I missing?
Your code:
ClientHandler ch = new ClientHandler(acceptedSocket);
ch.run();
doesn't start a new thread, it delegates to ClientHandler.run() in the same thread.
To start a thread, use new Thread( ch ).start(); since ch is of class ClientHandler which implements Runnable.
I am writing a single p2p file sharing program that will accept connections and also serve as server itself.
Its in process but Line: 60
Socket sock1= tcpSocket.accept();
throws a Null pointer Exception and i don't know whats wrong. Tried everything.
import java.net.*;
import java.io.*;
public class echoer implements Runnable {
int i,backlog;
public Socket tcpClient= null;
public ServerSocket tcpSocket= null;
public echoer(int tcpPort, int udpPort, int backlog) {
try {
this.tcpSocket = new ServerSocket(tcpPort,backlog);
System.out.println("Server connected to "+ InetAddress.getLocalHost() + "on TCP port " + tcpPort + "and UDP port " + udpPort );
this.backlog= backlog;
listening();
}
catch (SocketTimeoutException s) {
System.out.println("timeout");
}
catch (IOException ioe) {
System.out.println("could not listen on port 10009");
System.exit(-1);
}
}
public echoer () {
}
void listening(){
try {
//i++;
tcpSocket.getInetAddress();
System.out.println();
//Thread t1= new Thread((Runnable) new AcceptInput());
//t1.start();
//tcpSocket.accept();
//System.out.println("Connection accepted");
//messaging();
Thread t2 = new Thread((Runnable) new echoer());
t2.start();
}
catch (Exception e) {
System.out.println("Cannot accept connection");
}
}
public void Client(String addr, int port) throws IOException
{
System.out.println("address= "+ addr+ "port= "+ port);
tcpClient = new Socket(addr,port);
}
/*void messaging () {
System.out.println("Starting Thread");
Thread t = new Thread((Runnable) new echoer());
t.start();
}*/
public void run() {
while (true) {
try {
//System.out.println("Listening on "+ InetAddress.getLocalHost().getHostAddress() + "on TCP port " + tcpSocket.getLocalSocketAddress());
Socket sock1= tcpSocket.accept();
//Client(InetAddress.getLocalHost().getHostAddress(),tcpSocket.getLocalPort());
System.out.println("Connection accepted");
ObjectOutputStream out= new ObjectOutputStream(sock1.getOutputStream());
//Now start the messaging thread nad pass this sock1 to tcpClient
/*String line;
System.out.println("Write a message");
DataInputStream din= new DataInputStream(tcpClient.getInputStream());
line= din.readUTF();
if (line == null) {
din.close();
tcpClient.close();
}
System.out.println("Recvd message:" + line);*/
if (sock1 != null) {
tcpSocket.close();
}
}
catch (IOException o) {
System.out.println("Read Failed");
}
}
}
/*catch (IOException i) {
System.out.println("Last statement");
}
}*/
public static void main(String[] args) {
new echoer(Integer.parseInt(args[0]),Integer.parseInt(args[1]),5);
}
}
class AcceptInput implements Runnable {
String token;
public void run () {
BufferedReader br= new BufferedReader(new InputStreamReader(System.in));
try {
token= br.readLine();
if (token== "connect" ) {
System.out.print("Enter IP address: ");
BufferedReader ip= new BufferedReader(new InputStreamReader(System.in));
//accept ip and port
// pass ip and port to tcpclient socket to initiate a connection
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Here's the current problem, you call new Thread((Runnable) new echoer()) and this starts your thread.
However this calls the empty default constructor for echoer which currently has no actual code in it!
So even though you construct the sockets once, after you do that you just create a new instance of echoer with all new sockets and call run() on that
This means that all the sockets in run are null because they were never set and therefore through a NullPointerException when you try to use them.