java TCP Server doesn't send data to clients - java

I need to make a TCP Server which accepts sockets from clients and receives data from them and send received data to all clients. to do that my Server class saves accepted connections to an ArrayList<Socket> and while wants to send data to clients:
Arraylist<Socket> sockets=Server.getSockets();
for(Socket current: sockets)
{
ObjectOutputStream out=new ObjectOutputStream (current.getOutputStream());
out.flush();
out.writeObject(object);
out.flush();
out.close();
}
but it doesn't work. what's wrong?

There is nothing wrong with your code snippet, the only problem which I can feel is that how your client code is implemented. Let us say your client code is something like this.
Socket clientSocket = new Socket(ip, port);
BufferedReader inFromUser = new BufferedReader( new InputStreamReader(System.in));
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
while ( true ){
String sentence = inFromUser.readLine();
outToServer.writeBytes(sentence + '\n');
outToServer.flush();
DataInputStream is = new DataInputStream(clientSocket.getInputStream());
System.out.println(is.readLine());
}
Now this client is reading input from console and sending it to server, post that it blocks to wait for response. Lets assume server will send data to all[Which is what you want] if he receive a message 'fire'.
Now there are two clients connected to server, ClientA and ClientB.
1. ClientA blocked at user-input (console)
2. User enter 'abc'
3. ClientA moves on sends 'abc' to server
4. ClientA blocks to read data from server
5. Server sends back 'abc' to ClientA [Assuming its an echo server]
6. ClientA reads the data, print it
7. ClientA moves back(while loop), blocked again for user input.
Same thing happen for ClientB, so now both are blocked for user input from console.
Lets say now ClientA user send our magic word ['fire' in this case], server identifies that its a magic word and start sending data to ClientA and ClientB,
Now here the important thing to notice, which is the state of ClientA and ClientB, at this point ClientA has just send the data and is at point 4, hence is blocked to read data from server, so when server sends the message it can read and display, whereas clientB is at point 1, blocked for getting data from console.. so even though server has send data ClientB has data to read, but it can't since its stuck at point 1, also you are closing the connection from server after write, so if ClientB somehow after sometime moves from point 1 to point 4, socket is already closed, hence again it will not be able to read. Though server has send data to both ClientA and ClientB, only ClientA is able to get it.
Phew!! Quite a long explanation, I guess it gives you some direction to solve your problem
Server code for reference
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class BroadCastTCPServer {
private static ArrayList<Socket> sockets = new ArrayList<Socket>();
//Usage: java TCPServer port
public static void main(String args[]){
BroadCastTCPServer server = new BroadCastTCPServer();
try {
server.startServer("9999");
} catch (Exception e) {
e.printStackTrace();
}
}
private void startServer(String portStr) throws IOException {
int port = Integer.parseInt(portStr);
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Listening on IP:" + serverSocket.getInetAddress().getHostAddress() + " Port:"+port);
while(true){
Socket connectionSocket = serverSocket.accept();
sockets.add(connectionSocket);
System.out.println("New client connection:" + connectionSocket.getRemoteSocketAddress());
ClientHandler cl = new ClientHandler(connectionSocket);
Thread clientThread = new Thread(cl);
clientThread.start();
}
}
public void sendAll() throws Exception{
System.out.println("No of connections:" + sockets.size());
for(Socket current: sockets){
System.out.println(current.getRemoteSocketAddress());
ObjectOutputStream out=new ObjectOutputStream (current.getOutputStream());
out.flush();
out.writeObject("Tata\n");
out.flush();
//out.close();
}
}
class ClientHandler implements Runnable{
Socket socket;
public ClientHandler(Socket socket){
this.socket = socket;
}
#Override
public void run() {
BufferedReader inFromClient = null;
ObjectOutputStream out = null;
BufferedWriter br = null;
try {
inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out=new ObjectOutputStream (socket.getOutputStream());
OutputStreamWriter or= new OutputStreamWriter(out);
br = new BufferedWriter(or);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
while(true){
String clientSentence= null;
try {
clientSentence = inFromClient.readLine() ;
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("Received: " + clientSentence);
if (clientSentence.equalsIgnoreCase("fire")) {
try {
sendAll();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
try {
br.write(clientSentence + "\n" );
br.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}

Related

Server send message to client Sockets

I started working with sockets this week and I'm having a hard time.
My goal is when the client sent a message the server responded with a notification.
On the client side sending to the server has no problem, but when the server sends to the client nothing appears.
Can anybody help me with this problem?
Client:
Thread thread = new Thread(new myServerThread());
thread.start();
class myServerThread implements Runnable {
Socket socket;
ServerSocket serverSocket;
InputStreamReader inputStreamReader;
BufferedReader bufferedReader;
String message;
Handler handler = new Handler();
#Override
public void run() {
try {
serverSocket = new ServerSocket(5000);
while (true){
socket = serverSocket.accept();
inputStreamReader = new InputStreamReader(socket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader);
message = bufferedReader.readLine();
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), message,Toast.LENGTH_LONG).show();
}
});
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
SERVER:
String EMAIL = "Email";
try {
serverSocket = new ServerSocket(6000);
while(true){
socket = serverSocket.accept();
inputStreamReader = new InputStreamReader(socket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader);
email = bufferedReader.readLine();
System.out.println(email);
if(email.equals(EMAIL)){
jTextArea1.setText(email);
try {
socket = new Socket("localHost", 5000);
PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
printWriter.write(message);
printWriter.flush();
printWriter.close();
System.out.println("connected");
} catch (IOException e) {
e.printStackTrace();
}
}else{
}
}
} catch (IOException ex) {
}
etEmail = findViewById(R.id.etvEmail);
First the short answer: Your Java codes are both working almost fine.
Anyway, you should always test your application against another program that is known to be OK. By testing one self-written program against another fresh self-written program, it is difficult to say which of both is broken. It seems that you are testing it with some GUI (Android?). Transforming the relevant part to a simple console application which you run on a regular PC makes troubleshooting much easier.
So let me show how I checked your code on my Linux laptop:
First copy your "client" code into a "Hello-World" template. I added some debug messages and a loop which allows the client to receive more than one single line of text:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
class Main
{
static class myServerThread implements Runnable
{
Socket socket;
ServerSocket serverSocket;
InputStreamReader inputStreamReader;
BufferedReader bufferedReader;
String message;
#Override
public void run()
{
try
{
serverSocket = new ServerSocket(5000);
while (true)
{
System.out.println("Accepting...");
socket = serverSocket.accept();
System.out.println("Connected...");
inputStreamReader = new InputStreamReader(socket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader);
String message = bufferedReader.readLine();
while (message!=null)
{
System.out.println("Received:" + message);
message = bufferedReader.readLine();
}
System.out.println("Closing...");
socket.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
public static void main(String[] args)
{
Thread thread = new Thread(new myServerThread());
thread.start();
}
}
I started the "client" and opened another command window to open a network connection with Netcat and send two lines of text:
nc localhost 5000
Hallo
Test
The related output of the "client" program was:
Accepting...
Connected...
Received:Hallo
Received:Test
Closing...
Accepting...
So the "client" part is running fine obviously.
Next I copied your "server" code into a "Hello World" template:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
class Main
{
static class myServerThread implements Runnable
{
Socket socket;
ServerSocket serverSocket;
InputStreamReader inputStreamReader;
BufferedReader bufferedReader;
String message;
#Override
public void run()
{
String EMAIL = "Email";
try
{
serverSocket = new ServerSocket(6000);
while (true)
{
System.out.println("Accepting...");
socket = serverSocket.accept();
System.out.println("Connected...");
inputStreamReader = new InputStreamReader(socket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader);
String message = bufferedReader.readLine();
while (message != null)
{
System.out.println("Received:" + message);
if (message.equals(EMAIL))
{
System.out.println("Sending...");
try
{
socket = new Socket("localHost", 5000);
PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
printWriter.write(message);
printWriter.flush();
printWriter.close();
System.out.println("sending done");
}
catch (IOException e)
{
e.printStackTrace();
}
}
message = bufferedReader.readLine();
}
System.out.println("Closing...");
socket.close();
}
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}
public static void main(String[] args)
{
Thread thread = new Thread(new myServerThread());
thread.start();
}
}
Again I added some debug messages and a loop, so the server can receive multiple lines of text. Since this Java program handles two connections, I had to open two command windows.
In the first command window I tell NetCat to accept (listen) connection on port 5000. That is where your "server" will send the "Email" message to:
nc -lp 5000
In the second command window I tell Netcat to connect to your "server" on port 6000, then I send two lines of text and then I press Ctrl-C to stop it:
nc localhost 6000
Test
Email
^C
The related output of the "server" program is:
Accepting...
Connected...
Received:Test
Received:Email
Sending...
sending done
Closing...
Accepting...
And my listening Netcat in the other (first) command windows produced this output:
stefan#stefanpc:/hdd/stefan$ nc -lp 5000
Emailstefan#stefanpc:/hdd/stefan$
So everything looks fine on my machine. Beside one small detail: There is no line break after the "Email" that your "server" sends to the client (in this case NetCat). So the fix is simple:
printWriter.write(message+"\n");
This final line break is required because your client consumes the input by readLine().
NetCat is a very helpful tool to test plain text TCP socket communication. It is included in all Linux distributions. If you have difficulties to find a Windows executable, then take it from my homepage: http://stefanfrings.de/avr_tools/netcat-win32-1.12.zip
Please comment if that was helpful to you.

Server Client Communication via Internet (Java)

I have written a simple Java TCP Server and a Client (See below).
The idea is quite simple: the Client sends a message to the Server the Server reads it, modify it and sends it back to the client.
import java.io.*;
import java.net.*;
public class ServerTest2 {
public static void main(String[] argv) {
try {
ServerSocket serverSocket = new ServerSocket(2000); // Create Socket and bind to port 2000
System.out.println("Created");
Socket clientSocket = serverSocket.accept(); //Wait for client and if possible accept
System.out.println("Connection accepted");
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())); // for outputs
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); // for inputs
String request; // requst/input of client
String answer; // the answer for the client
System.out.println("Start Waiting");
request = br.readLine(); //Wait for input from client
answer = "answer to "+request;
bw.write(answer); // Send answer to client
System.out.println("send");
bw.newLine();
bw.flush();
//Shut everything down
bw.close();
br.close();
clientSocket.close();
serverSocket.close();
}
catch (Exception e) {
System.out.println(e);
}
}
}
The Client Implementation
import java.io.*;
import java.net.*;
public class ClientTest2 {
public static void main(String[] argv) {
try {
String host = "185.75.149.8"; //public ip of router
Socket clientSocket = new Socket(host,2000); //Create and connect Socket to the host on port 2000
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())); // for outputs
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); // for inputs
String answer;
String request = "HelloWorld";
bw.write(request); //Write to server
bw.newLine();
bw.flush();
System.out.println("Waiting");
answer = br.readLine(); //Wait for answer
System.out.println("Host = "+host);
System.out.println("Echo = "+answer);
//Shut eveything down
bw.close();
br.close();
clientSocket.close();
}
catch (Exception e) {
System.out.println(e);
}
}
}
It works perfectly on my local network.
Now I want to use it via the Internet so I installed Port Forwarding on Port 2000 in my Router which sends it to Port 2000 of my PC.
My PC is directly connected to my Router without any Subnets in between.
The Problem is that the Server does not accept the connection(Stops at serverSocket.accept()).
It does not throw an Exception it just waits forever.
The Client does also not throw an Exception (If the Port isn't open it would throw a Connection refused Exception)
This means that the Port Forwarding should work (I have also tested whether the port is open with a Webtool (its open)).
But strangely the Client stops waiting after about 10 seconds and continues with the program.
Since the Port Forwarding should work and my Code works fine in my local Network I absolutely don't know how or where I could find the problem.
I appreciate any help.
Thank you very much!

java Socket programming Server Client

I'm trying to program a Server Client program where the CLIENT will be prompt if the SERVER closes or loses connection. What happens is once I connect the server and the client then disconnects the server it doesn't go to the ConnectException part
example: I opened the Server and Client connects, in the Client it will show that "You are connected to the Server", then if the Server disconnects there should be a "Server is disconnected". and when the Server reopens it will prompt the Client that he's connected to the Server
How can I continuously check if the Server is open or disconnected
here's my code:
SERVER
public class Server
{
private static Socket socket;
public static void main(String[] args)
{
try
{
int port = 25000;
ServerSocket serverSocket = new ServerSocket(port);
//Server is running always. This is done using this while(true) loop
while(true)
{
//Reading the message from the client
socket = serverSocket.accept();
System.out.println("Client has connected!");
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String number = br.readLine();
System.out.println("Message received from client is "+number);
//Multiplying the number by 2 and forming the return message
String returnMessage;
try
{
int numberInIntFormat = Integer.parseInt(number);
int returnValue = numberInIntFormat*2;
returnMessage = String.valueOf(returnValue) + "\n";
}
catch(NumberFormatException e)
{
//Input was not a number. Sending proper message back to client.
returnMessage = "Please send a proper number\n";
}
//Sending the response back to the client.
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(returnMessage);
System.out.println("Message sent to the client is "+returnMessage);
bw.flush();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
CLIENT
public class Client
{
private static Socket socket;
public static void main(String args[])
{
Scanner input=new Scanner(System.in);
try
{
String host = "localhost";
int port = 25000;
InetAddress address = InetAddress.getByName(host);
socket = new Socket(address, port);
System.out.println("Connected to the Server");
}
catch (ConnectException exception)
{
System.out.println("Server is still offline");
}
catch(IOException ex)
{
System.out.println("Server got disconnected");
}
}
}
Well, the best way to tell if your connection is interrupted is to try to read/write from the socket. If the operation fails, then you have lost your connection sometime.
So, all you need to do is to try reading at some interval, and if the read fails try reconnecting.
The important events for you will be when a read fails - you lost connection, and when a new socket is connected - you regained connection.
That way you can keep track of up time and down time.
you can do like this
try
{
Socket s = new Socket("address",port);
DataOutputStream os = new DataOutputStream(s.getOutputStream());
DataInputStream is = new DataInputStream(s.getInputStream());
while (true)
{
os.writeBytes("GET /index.html HTTP/1.0\n\n");
is.available();
Thread.sleep(1000);
}
}
catch (IOException e)
{
System.out.println("connection probably lost");
e.printStackTrace();
}
or you can simply et connection time out like this socket.setSoTimeout(timeout); to check connectivity
or you can use
socket.getInputStream().read()
makes the thread wait for input as long as the server is connected and therefore makes your program not do anything - except if you get some input and
returns -1 if the client disconnected
or what you can do is structure your code in this way
while(isConnected())
{
// do stuffs here
}

Handle streams with multiple clients?

basically what i want to do is develop a chat program(something between an instant messenger and IRC) to improve my java skills.
But I ran into 1 big problem so far: I have no idea how to set up streams properly if there is more than one client. 1:1 chat between the client and the server works easily, but I just don't know what todo so more than 1 client can be with the server in the same chat.
This is what I got, but I doubt its going to be very helpful, since it is just 1 permanent stream to and from the server.
private void connect() throws IOException {
showMessage("Trying to connect \n");
connection = new Socket(InetAddress.getByName(serverIP),27499);
showMessage("connected to "+connection.getInetAddress().getHostName());
}
private void streams() throws IOException{
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
showMessage("\n streams working");
}
To read from multiple streams in one program, you're going to have to use multithreading. Because reading from streams is synchronous, you'll need to read from one stream for each thread. See the java tutorial on threads for more info on multithreading.
I've done this several times with ServerSocket(int port) and Socket ServerSocket.accept(). This can be pretty simple by having it listen to the one port you want your chat server client listening on. The main thread will block waiting for the next client to connect, then return the Socket object to that specific client. Usually you'll want to put them in a list to generically handle n-number of clients.
And, yes, you will probably want to make sure each Socket is in a different thread, but that's entirely up to you as the programmer.
Remember, there is no need to re-direct to another port on the server, by virtue of the client using a different source port, the unique 5-tuple (SrcIP, SrcPort, DstIP, DstPort, TCP/UDP/other IP protocol) will allow the one server port to be re-used. Hence why we all use stackoverflow.com port 80.
Happy Coding.
Made something like that a few months back. basically I used a separate ServerSocket and Thread per client server side. When client connects you register that port's input and output streams to a fixed pool and block until input is sent. then you copy the input to each of the other clients and send. here is a basic program run from command line:
Server code:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class ChatServer {
static int PORT_NUMBER = 2012;
public static void main(String[] args) throws IOException {
while (true) {
try (ServerSocket ss = new ServerSocket(PORT_NUMBER)) {
System.out.println("Server waiting #" + ss.getInetAddress());
Socket s = ss.accept();
System.out.println("connection from:" + s.getInetAddress());
new Worker(s).start();
}
}
}
static class Worker extends Thread {
final static ArrayList<PrintStream> os = new ArrayList(10);
Socket clientSocket;
BufferedReader fromClient;
public Worker(Socket clientSocket) throws IOException {
this.clientSocket = clientSocket;
PrintStream toClient=new PrintStream(new BufferedOutputStream(this.clientSocket.getOutputStream()));
toClient.println("connected to server");
os.add(toClient);
fromClient = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
}
#Override
public void run() {
while (true) {
try {
String message = fromClient.readLine();
synchronized (os) {
for (PrintStream toClient : os) {
toClient.println(message);
toClient.flush();
}
}
} catch (IOException ex) {
//user discnnected
try {
clientSocket.close();
} catch (IOException ex1) {
}
}
}
}
}
}
Client code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException {
final BufferedReader fromUser = new BufferedReader(new InputStreamReader(System.in));
PrintStream toUser = System.out;
BufferedReader fromServer;
final PrintStream toServer;
Socket s = null;
System.out.println("Server IP Address?");
String host;
String port = "";
host = fromUser.readLine();
System.out.println("Server Port Number?");
port = fromUser.readLine();
s = new Socket(host, Integer.valueOf(port));
int read;
char[] buffer = new char[1024];
fromServer = new BufferedReader(new InputStreamReader(s.getInputStream()));
toServer = new PrintStream(s.getOutputStream());
new Thread() {
#Override
public void run() {
while (true) {
try {
toServer.println(">>>" + fromUser.readLine());
toServer.flush();
} catch (IOException ex) {
System.err.println(ex);
}
}
}
}.start();
while (true) {
while ((read = fromServer.read(buffer)) != -1) {
toUser.print(String.valueOf(buffer, 0, read));
}
toUser.flush();
}
}
}

Java Mulithreaded Server Client

I have a question, I'm currently working on a little project of mine and stumbled upon a dead end. I have a Java Server :
import java.io.*;
import java.net.*;
class TCPServer
{
public static void main(String argv[]) throws Exception
{
ServerSocket welcomeSocket = new ServerSocket(3443);
Socket clientSocket =null;
ClientHandler ch;
while(true)
{
try{
clientSocket = welcomeSocket.accept();
System.out.println("Client connected on port :"+clientSocket.getPort());
ch = new ClientHandler (clientSocket);
Thread t = new Thread(ch);
t.start();
}catch (Exception e){
System.out.println("SERVER CRASH");
}
}
}
}
Then the client connects through the port 3443, a new thread is created with ClientHandler. Now is the problem, in the client side the socket used to connect is still on port 3443, but on the server side the thread is on an arbitrary port, let's say 5433, so the server can communicate with the thread but not the client, because it has no knowledge of what port the thread is using... I'm a bit confused with all this, does the client class is only needed to make the initial connection, then all the communication is done through the ClientHandler class, if so should i also instantiate an object of ClientHandler in the client class?
Here's my client class :
import java.io.*;
import java.net.*;
class TCPClient
{
static Socket clientSocket = null;
public static void main(String argv[]) throws Exception
{
BufferedReader k = new BufferedReader(new InputStreamReader(System.in));
BufferedReader ine = null;
DataOutputStream oute = null;
try{
clientSocket = new Socket("localhost", 3443);
oute = new DataOutputStream(clientSocket.getOutputStream());
ine = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (UnknownHostException e) {
System.out.println("Unknown host");
System.exit(1);
} catch (IOException e) {
System.out.println("No I/O");
System.exit(1);
}
try{
//send
oute.writeBytes(k.readLine());
//recieve
String line = ine.readLine();
System.out.println("Text received: " + line);
} catch (IOException e){
System.out.println("Read failed");
System.exit(1);
}
}
}
The problem is the socket created in client is still connected to Port 3443, and the server is listening to this port, so I won't recieve anything from the server (infinite loop). The clientHandler is on another port. Am i doing it wrong?
You’re calling accept() twice. Call it only once and store the resulting Socket in a variable that you can then hand in to new ClientHandler().
Oh, also, the Socket knows both sides of the communication so it won’t be confused by whatever port the client uses.

Categories