I have a class which is a socket client and I am trying to unit test its methods. The tests require that I start a socket server before each test so I use:
#Before
public void setUp() {
if (myServerSocket == null) {
Thread myThread = new Thread() {
public void run() {
DataInputStream dis = null;
DataOutputStream dos = null;
try {
ServerSocket myServer = new ServerSocket(port);
myServerSocket = myServer.accept();
dis = new DataInputStream(myServerSocket.getInputStream());
dos = new DataOutputStream(myServerSocket.getOutputStream());
byte[] bytes = new byte[10];
dis.read(bytes);
boolean breakLoop = false;
do {
if (new String(bytes).length() != 0) {
dos.writeBytes(serverMessage + "\n");
dos.flush();
breakLoop = true;
dos.writeBytes("</BroadsoftDocument>" + "\n");
dos.flush();
}
} while (!breakLoop);
}
catch (IOException e) {
e.printStackTrace();
}
}
};
myThread.start();
}
}
After each test I try to close the server socket so I can reopen the server socket for the next test:
#After
public void tearDown() throws IOException, BroadsoftSocketException {
System.out.println("#After");
if (myServerSocket != null) {
myServerSocket.close();
myServerSocket = null;
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {
// do nothing.
}
}
}
However, I get "java.net.BindException: Address already in use: JVM_Bind" before each test starting with the second test. I realize I am trying to use the same port for each test but shouldn't closing the socket free up the port?
Quite possibly your socket is still in TIME_WAIT state when you attempt to reconnect it. I would recommend mocking such external dependencies, but if you really do find yourself wanting to continue using a real socket then try setting rebind options. In your setup function, instead of ServerSocket myServer = new ServerSocket(port); do :
final ServerSocket myServer = new ServerSocket();
myServer.setReuseAddress(true);
myServer.bind(new java.net.InetSocketAddress(port));
You already close your serversocket in "setUp" and you really should do it in a finally block.
The port may not be freed immediately. You can avoid this by setting the ServerSocket's reuseAdress to true. See setReuseAddress.
And I second SimonC: maybe you are better off avoiding the socket in the first place.
Related
Relevant code:
#Test
public void serverTest() throws IOException {
GameServer server = new GameServer();
server.start(9000);
GameClient client1 = new GameClient();
GameClient client2 = new GameClient();
client1.startConnection("localhost", 9000);
client2.startConnection("localhost", 9000);
client1.sendMessage("Hey I am client 1");
client2.sendMessage("Hey I am client 2");
}
public class GameServer {
private ServerSocket serverSocket;
public void start(int port) throws IOException {
System.out.println("Server started !!!");
serverSocket = new ServerSocket(port);
while (true) {
new Thread(new GameClientHandler(serverSocket.accept())).start();
}
}
public void stop() throws IOException {
serverSocket.close();
}
private static class GameClientHandler implements Runnable {
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public GameClientHandler(Socket socket) {
this.clientSocket = socket;
}
#Override
public void run() {
System.out.println(Thread.currentThread().getName());
try {
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine = in.readLine();
while ((inputLine = in.readLine()) != null){
System.out.print(inputLine);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
in.close();
out.close();
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Why can't the server and client be started together in the #Test? I think it gets stuck in the infinite while loop but at the same time, shouldn't there be context switching with the new threads started after accepting the connection?
I expected at least the name of the 2 new threads to be printed but it doesn't happen.
Let us look carefully to your test code:
GameServer server = new GameServer();
Ok, this lines creates a server, and the test thread is ready to execute next line
server.start(9000);
Ok, the test thread starts the server, and will be ready to execute the next line when the start method will return.
What happens in start:
System.out.println("Server started !!!");
Ok, you should see that message
serverSocket = new ServerSocket(port);
Ok, you have created a ServerSocket
while (true) {
new Thread(new GameClientHandler(serverSocket.accept())).start();
}
ok you a waiting for a connection (at serverSocket.accept()), will create a new thread to handle it as soon as you will get one, and loop again.
But as this point, the test thread is waiting and will never go to the following line to start the first connection. And it will remain stuck unless something else (maybe another thread) starts those damned connections.
The method GameServer.start will only return with an exception. That is because you have the while-loop.
So your test execution will start the server and wait for someone to open a connection, but that never happens.
I want to integrate a server with multiple clients for a blackjack game I created, and thus I began practicing with servers in java. I create a thread, that when ran, forces the server to listen for input and produce an output. Then I added a feature to stop the server. However, the server randomly produces the correct output, and sometimes fails to connect. Here is the code for when the user hosts a server:
st = new ServerThread(); //this is a field of type ServerThread
st.start(); //this runs the server concurrently as a new thread
Here is the code for when they close a server:
st.stopThread();
Finally, here is the source for the serverThread:
public class ServerThread extends Thread {
private volatile boolean isRunning = true;
private Socket socket;
private static final int PORTNUM = 1342;
#Override
public void run() {
while (isRunning) { //should run only when the
try {
ServerSocket serverSocket = new ServerSocket(PORTNUM); //uses the same port number, which I made a constant
//Reading the an object of type Information from the client
socket = serverSocket.accept();
ObjectInputStream serverInputStream = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream serverOutputStream = new ObjectOutputStream(socket.getOutputStream());
Information i = (Information) serverInputStream.readObject();
//arbitrarily changes the data stored in the information object to verify connection with server
i.setI(100);
i.setS("new string");
i.setD(4.4);
//sends the modified object back to the client
serverOutputStream.writeObject(i);
serverInputStream.close();
serverOutputStream.close();
socket.close();
} catch (IOException e) {
//System.out.println("IOException");
//e.printStackTrace();
} catch (ClassNotFoundException e) {
//System.out.println("ClassNotFoundException");
//e.printStackTrace();
} finally {
try {
if (socket != null) { //avoid null pointer if no connections have been established
socket.close();
}
} catch (IOException ex) {
//Logger.getLogger(ServerThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public void stopThread() {
isRunning = false;
}
}
Any suggestions on edits to make my code perform correctly and consistently would be welcome. Thanks.
I would move the socket definition away from being an instance variable i.e,
while (isRunning) {
Socket socket = null;
try {
...
The once the client disconnects and I restart the client, the server gives read line timeout. and when I run the server again, it works fine. So after disconnect one time I get read line timeout exception and next time it works.
import java.io.*;
public class TcpServer {
ServerSocket welcomeSocket;
public TcpServer() throws IOException{
createSocket(port);
}
public TcpServer(int port) throws IOException{
createSocket(port);
}
private void createSocket(int port) throws IOException{
welcomeSocket = new ServerSocket(port);
}
#Override
public void listen() throws IOException{
boolean exitServer = false;
Socket connectionSocket = null;
try {
while (!exitServer ) {
if(...){
exitServer = true;
}
}
}
} catch (IOException e) {
try {
welcomeSocket.accept();
listen();
} catch (IOException e1) {
System.out.println("Cannot open connection!!!");
}
}
}
}
The ServerSocket.accept() method blocks and returns a new client socket connection when someone tries to connect. Put it in a while loop and then spawn a thread for this new socket worker. Something similar to this:
ServerSocket welcomeSocket = new ServerSocket(port);
while (true) {
Socket socket = welcomeSocket.accept();
new Thread(new RunnableSocketWorker(socket));
}
If your client does decide to disconnect, that's fine, let them. You want the socket worker that was working on it to exit. If a new client tries to connect, they will do so above with your ServerSocket object and this infinite loop.
A big reason sockets are relatively easy in Java is that this ServerSocket class handles all incoming new clients. Why would you want to code that part yourself?
Just take the socket it returns and have fun!
I'm trying to make a simple client-server networking program. Initially, I was not running the Server and Client objects concurrently. The command prompt would just get stuck on trying to run the program. I then decided to use threads. The result is the same; I believe I have to use wait() and notify() somewhere but I'm not able to get it.
The Server needs to run first, but it will have to wait for the incoming Socket reference before it can proceed. I believe some lines need to be shifted here and there before a wait-and-notify mechanism is implemented. Here's my code so far -:
package networking;
import java.net.*;
import java.io.*;
import java.util.Scanner;
class Server implements Runnable
{
ServerSocket ss;
Socket incoming;
public void run()
{
try
{
ss = new ServerSocket(8189);
incoming = ss.accept();
OutputStream outs = incoming.getOutputStream();
InputStream ins = incoming.getInputStream();
Scanner in = new Scanner(ins);
PrintWriter out = new PrintWriter(outs);
out.println("Hello, Bye to exit");
out.println("This is the server program");
out.println("It will echo client stuff");
boolean done = false;
while(!done && in.hasNextLine())
{
out.println("Echo: " + in.nextLine());
if(in.nextLine().trim().equals("Bye"))
done = true;
}
incoming.close();
}
catch(IOException e)
{
System.err.println(e.getMessage());
}
}
}
class Client implements Runnable
{
Socket s;
public void run()
{
try
{
s = new Socket("localhost", 8189);
InputStream ins = s.getInputStream();
OutputStream outs = s.getOutputStream();
Scanner in = new Scanner(ins);
PrintWriter out = new PrintWriter(outs);
while(in.hasNextLine())
System.out.println("Client: " + in.nextLine());
out.println("Bye");
s.close();
}
catch(IOException e)
{
System.err.println(e.getMessage());
}
}
}
public class Networking
{
public static void main(String... args)
{
Thread server = new Thread(new Server());
Thread client = new Thread(new Client());
server.start();
client.start();
}
}
Any tips and pointers would be much appreciated; I just need a nod(or more) in the right direction.
Your code for opening serve and client is correct. But the problem is in the while loop for reading or writing data it falls in a deadlock. Because after establishing the connection booth server and client is waiting for each other to write something in the stream. Try with this.
class Server implements Runnable {
ServerSocket ss;
Socket incoming;
public void run() {
try {
System.out.println("Server STarted");
ss = new ServerSocket(8189);
incoming = ss.accept();
System.out.println("Client accepted");
OutputStream outs = incoming.getOutputStream();
InputStream ins = incoming.getInputStream();
Scanner in = new Scanner(ins);
PrintWriter out = new PrintWriter(outs);
out.println("Hello, Bye to exit");
out.println("This is the server program");
out.println("It will echo client stuff");
boolean done = false;
while (!done) { // && in.hasNextLine()
// out.println("Echo: " + in.nextLine());
// if (in.nextLine().trim().equals("Bye")) {
// done = true;
// }
out.println("TEsting from server");
}
incoming.close();
System.out.println("End server");
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
}
The following code is correct when compiled, but when run it says: ConnectException
the error image:
import java.net.*;
import java.io.*;
class TcpChat
{
public static void main(String[] args) throws Exception
{
Socket s = new Socket("Ip",20000);
ServerSocket ss = new ServerSocket(20000);
new Thread(new TcpClient(s)).start();
new Thread(new TcpServer(ss)).start();
}
}
class TcpClient implements Runnable
{
Socket s;
TcpClient(Socket s)
{
this.s = s;
}
public void run()
{
try
{
OutputStream out = s.getOutputStream();
out.write("hello javaserver".getBytes());
s.close();
}
catch (Exception e)
{
}
}
}
class TcpServer implements Runnable
{
ServerSocket ss;
TcpServer(ServerSocket ss)
{
this.ss = ss;
}
public void run()
{
try
{
Socket s = ss.accept();
InputStream in = s.getInputStream();
byte[] buf =new byte[1024];
int length =in.read(buf);
String ip =s.getInetAddress().getHostAddress();
String data = new String(buf,0,length);
System.out.println(ip+":::"+data);
s.close();
ss.close();
}
catch (Exception e)
{
}
}
}
Additionally, there is no error about the IP address I use, in my PC I use my own IP.
You didn't post your whole code, so it's hard to check, but it seems like you try to connect to a port (i.e. open the client socket) before you actually open the server socket. That won't work, of course, since there's nothing listening at that port yet (thus: connection refused).
Change your main method like
ServerSocket ss = new ServerSocket(20000);
Socket s = new Socket("127.0.0.1", 20000);
new Thread(new TcpServer(ss)).start();
new Thread(new TcpClient(s)).start();
You can find a better example for Chat Server here. Also you can read about sockets from here