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.
Related
I have created this code snippet in both a single threaded version and multithreaded for a client/server setup I have going. I have tested both (recording the avg turn around time) and have gotten EXTREMELY similar results within margin of error when running multiple simple server commands at once. have I implememnted my client handler wrong?
This is my first time trying to implement a multithreaded server and from my understanding it just a matter of putting in a client handler being
`
class ServerThread extends Thread {
private Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
`
below is the snippet of the whole server code.
`
public class Server {
public static void main(String[] args) {
if (args.length < 1) return;
int port = Integer.parseInt(args[0]);
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("Server is listening on port " + port);
while (true) {
Socket socket = serverSocket.accept();
System.out.println("New client connected");
new ServerThread(socket).start();
}
} catch (IOException ex) {
System.out.println("Server exception: " + ex.getMessage());
ex.printStackTrace();
}
}
}
class ServerThread extends Thread {
private Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
public void run() {
try {
InputStream input = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
OutputStream output = socket.getOutputStream();
PrintWriter writer = new PrintWriter(output, true);
String text;
do {
text = reader.readLine(); // reads text from client
Process p = Runtime.getRuntime().exec(text);
BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
String outputLine;
while ((outputLine = stdout.readLine()) != null) { // while serverMsg is not empty keep printing
writer.println(outputLine);
}
stdout.close();
writer.println("ENDCMD");
// Text here should just write back directly what the server is reading...?
}
while (!text.toLowerCase().equals("exit"));
socket.close();
} catch (IOException ex) {
System.out.println("Server exception: " + ex.getMessage());
ex.printStackTrace();
}
}
}
`
I have tested both (recording the avg turn around time) and have gotten EXTREMELY similar results within margin of error when running multiple simple server commands at once. have I implememnted my client handler wrong?
If you are not making a new connection for each command that you send, then this would be expected. Since each connection runs on one thread, a multi-threaded approach, as you have shown, would have the same speed as if you didn't make a new thread for each connection. The difference is that, without multi-threading, you can only have one connection at a time.
I have my server code below over here:
public void startServer() {
ServerSocket listener = selectUnusedPortFromRange(1024, 65535);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
String command = null;
while (true) {
Socket socket = listener.accept();
System.out.println("Got a connection from: " + socket.getLocalPort());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
command = in.readLine();
System.out.println("GOT HERE"); //Not being printed out
if (command != null && !"".equals(command)) {
if ("connection".equals(command)) {
Writer writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
writer.write("success\n");
writer.flush();
}
}
}
}
}
}
t.start();
}
This is my client side:
public void makeConnection() {
try {
Socket socket = new Socket(IP, PORT);
Writer writer = new PrintWriter(socket.getOutputStream(), true);
writer.write("connection\n");
BufferedReader socketRead = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str;
while ((str = socketRead.readLine()) != null) {
if ("success".equals(str)) {
System.out.println("Successfully saved all hosts to: " + listOfHosts.get(i));
socketRead.close();
socket.close();
iStream.close();
writer.close();
}
}
}catch (Exception e) {
System.out.println(e.getMessage());
}
}
On the client side after I create my socket to the connect to the server I write "connection" into the outputStream of the socket and wait for an acknowledgement back from the server saying success. For some reason the connection is not being made to the server. In the server System.out.println("Got a connection from: " + socket.getLocalPort()); this line is not being printed out.
Is there something wrong that I am doing. I can't spot it. And I am not getting an exception thrown when I try to connect to my server.
1) Make sure you use the same port for both the Client and Server. They must communicate over the same port. It seems you may be using different ports currently.
2) Make sure you actually start your server thread. As-is in your code above, you make a new Thread, but never start it. t.start() must be called somewhere.
3) If this is on your local machine, you may be better off using localhost instead of the actual IP address. Firewalls might treat your external IP differently.
4) Terminate your messages with a newline character, such as \n, so that your BufferedReader can use it's readLine() method. For good measure, also follow-up by flushing the writer's buffer, just in case the newline character didn't trigger that. writer.flush();
And lastly, make sure you terminate the JVM before trying to run your code again. Your code has not shutdown mechanism to un-bind the server from the port... so you may get an exception thrown telling you the port and/or address are already in use. If that happens, either change ports, or kill the java process running in the background.
Here is your code, slightly modified to run on my system. It's working as you might expect it to. I tried to change as little as possible just to get it working on my system. One note is, I hard-coded the port number into the server and client - that's not required, it was just convenient for me to test with:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
public class Test {
public static void main(String[] args) throws IOException {
Test test = new Test();
test.startServer();
test.makeConnection();
}
public void startServer() throws IOException {
final ServerSocket listener = new ServerSocket(60001);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
String command = null;
while (true) {
Socket socket = listener.accept();
System.out.println("Got a connection from: " + socket.getLocalPort());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
command = in.readLine();
System.out.println("GOT HERE");
if (command != null && !"".equals(command)) {
if ("connection".equals(command)) {
Writer writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
writer.write("success\n");
writer.flush();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.start();
}
public void makeConnection() {
System.out.println("Making Connection");;
try {
Socket socket = new Socket("localhost", 60001);
Writer writer = new PrintWriter(socket.getOutputStream(), true);
writer.write("connection\n");
writer.flush();
BufferedReader socketRead = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str;
while ((str = socketRead.readLine()) != null) {
if ("success".equals(str)) {
System.out.println("Successfully saved all hosts to: "); //+ listOfHosts.get(i));
socketRead.close();
socket.close();
//iStream.close();
writer.close();
}
}
}catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
I was facing the exact same issue. I overcame it by using an ACK mechanism (Wasn't my idea, it was suggested to me). The idea is that client would make a request to server and keep the socket connection alive (and the ouput stream open) till server responds back an agreed ACK message over the same channel. Once the client receives the ACK message, only then it would close the connection.
Below is the code for Server :-
final ServerSocket listener = new ServerSocket(11111);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
String command = null;
while (true) {
System.out.println("About to accept");
Socket socket = listener.accept();
System.out.println("Got a connection from: " + socket.getLocalPort());
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
StringBuilder str = new StringBuilder(inputStream.readUTF());
//command = in.readLine();
System.out.println("GOT HERE. Msg received : "+str);
if (str != null && !"".equals(str.toString())) {
command = str.toString();
if ("connection".equals(command)) {
System.out.println("Got connection message");
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
outputStream.writeUTF("connection");
outputStream.close();
}
}
inputStream.close();
System.out.println("Done");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
});
t.start();
}
Client :-
public void makeConnection() {
try {
System.out.println("In makeConnection");
Socket socket = new Socket("127.0.0.1", 11111);
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
outputStream.writeUTF("connection");
InputStream inputStream = socket.getInputStream();
DataInputStream dataInputStream = new DataInputStream(inputStream);
StringBuilder str;
do {
str = new StringBuilder(dataInputStream.readUTF());
} while (!str.toString().equals("connection"));
System.out.println("Successfully saved all hosts to: ");
outputStream.close();
dataInputStream.close();
socket.close();
outputStream.close();
}catch (Exception e) {
System.out.println(e.getMessage());
}
}
A call to start the proceedings :-
public void start() throws IOException, InterruptedException {
System.out.println("Starting server");
startServer();
Thread.sleep(1000);
System.out.println("Starting connection");
makeConnection();
}
i am creating a LAN game that accepts strings and parses them from structured english and displays them on a grid. i have created the server and client and it works but im having some issues. when i send a string it doesnt appear on the other machine right away. for some reason the string is only sent to the other machine once the other machine sends something over. i dont know why this happens. Could you please help me find out why it doesnt send straight away. Thanks
Server Code:
import java.awt.Point;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class studentServer{
static ServerSocket serverSocket;
static Socket socket;
static PrintWriter printWriter;
static BufferedReader bufferedReader;
static Thread thread;
Console console = new Console();
public ServerPlayergameMain gm;
public static void main(String args[]) throws Exception{
}
public void run(String commandMessage){
while(true){
try{
printWriter.println(commandMessage+"\n");
String input = bufferedReader.readLine();//reads the input from textfield
console.readLine("Client message: "+input);//Append to TextArea
}catch(Exception e){}
}
}
public void serverStartActionPerformed() {
System.out.println("Server has started!");
try{
serverSocket = new ServerSocket (8888); // socket for the server
socket = serverSocket.accept(); // waiting for socket to accept client
JOptionPane.showMessageDialog(null, "Your opponent has connected!", "Opponent Connection!", JOptionPane.INFORMATION_MESSAGE);
gm = new ServerPlayergameMain();
gm.setVisible(true);
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); // reads line from input streamer
printWriter = new PrintWriter(socket.getOutputStream(),true);
}catch(IOException | HeadlessException e){
System.out.println("Server not running!"); //print message if server is not running
}
}
}
Client Code:
import java.io.*;
import java.net.*;
import javax.swing.JOptionPane;
public class StudentClient {
static Socket socket;
static PrintWriter printWriter;
static BufferedReader bufferedReader;
static Thread thread;
Console console = new Console();
public ClientPlayergameMain gm;
public void Clients(String address) {
try{
socket=new Socket("localhost",8888);//Socket for client
//below line reads input from InputStreamReader
bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//below line writes output to OutPutStream
printWriter=new PrintWriter(socket.getOutputStream(),true);
JOptionPane.showMessageDialog(null, "Connected to server successfully", "Success", JOptionPane.INFORMATION_MESSAGE);
gm = new ClientPlayergameMain();
gm.setVisible(true);
System.out.println("Connected");//debug code
}catch(Exception e){
JOptionPane.showMessageDialog(null, "No Connection to server", "Error", JOptionPane.ERROR_MESSAGE);
System.out.println("Not Connected");
}
}
public static void run(String commandMessage){
while(true){
try{
printWriter.println(commandMessage+"\n");
String input = bufferedReader.readLine();
System.out.println("From server:" +input);
}catch(Exception e) {}
}
}
}
The code works but i dont know why there is a condition for the other machine to send something.
Thanks for your time.
A lot of compilation problems are there in you code. Some of the classes and objects are missing to resolve.
Still I have tried it to figure out the issue.
It may be the reasons:
sending new line character \n in printWriter.println(commandMessage+"\n"); statement, just remove \n.
client and server both are writing first in printWriter.println(commandMessage+"\n"); statement, make it last in anyone class
Here is the code:
StudentServer.java:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class StudentServer {
static ServerSocket serverSocket;
static Socket socket;
static PrintWriter printWriter;
static BufferedReader bufferedReader;
static Thread thread;
public static void main(String args[]) throws Exception {
StudentServer studentServer = new StudentServer();
studentServer.serverStartActionPerformed();
studentServer.run("server");
}
public void run(String commandMessage) {
if (true) {
try {
printWriter.println(commandMessage);
String input = bufferedReader.readLine();// reads the input from textfield
System.out.println("Client message: " + input);// Append to TextArea
} catch (Exception e) {
}
}
}
public void serverStartActionPerformed() {
System.out.println("Server has started!");
try {
serverSocket = new ServerSocket(8888); // socket for the server
socket = serverSocket.accept(); // waiting for socket to accept client
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); // reads
// line
// from
// input
// streamer
printWriter = new PrintWriter(socket.getOutputStream(), true);
} catch (Exception e) {
e.printStackTrace();
System.out.println("Server not running!"); // print message if server is not running
}
}
}
StudentClient.java:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class StudentClient {
static Socket socket;
static PrintWriter printWriter;
static BufferedReader bufferedReader;
static Thread thread;
public void clients() {
try {
socket = new Socket("localhost", 8888);// Socket for client
// below line reads input from InputStreamReader
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// below line writes output to OutPutStream
printWriter = new PrintWriter(socket.getOutputStream(), true);
System.out.println("Connected");// debug code
} catch (Exception e) {
System.out.println("Not Connected");
}
}
public void run(String commandMessage) {
if (true) {
try {
String input = bufferedReader.readLine();
System.out.println("From server:" + input);
printWriter.println(commandMessage);
} catch (Exception e) {
}
}
}
public static void main(String args[]) throws Exception {
StudentClient studentClient = new StudentClient();
studentClient.clients();
studentClient.run("client");
}
}
Have you tried printWriter.flush() after each write/print?
There are quite a few little problems, as Braj points out. The main one is in this sequence on your server side:
serverSocket = new ServerSocket (8888); // socket for the server
socket = serverSocket.accept(); // BLOCKS waiting for socket to accept client
// ..
printWriter = new PrintWriter(socket.getOutputStream(),true);
This means that printWriter, which you use to write to the client, doesn't even exist until after the server has listened for, blocked waiting on, and accepted a connection from the client.
If you want the connection to be opened for reading and writing without seeming to send anything from the client, send a handshake from the client. You could copy SMTP, and use HELO <myname>. That even tells the server who's calling.
Update after further reading:
I've always done like you have, and used the implicit connect that happens when you use getOutputStream() on the client side. However, Socket does allow you to connect an existing socket manually, using Socket#connect(). Try that, maybe it will work better than a handshake, for you.
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();
}
}
}
Environment: Java 6, windows xp
I am trying to write a client-server TCP socket application. Need to detect on the server, when the client has closed the socket. All the information on the Internet, says that the server will throw a socket exception when its not able to write.
However, when I run the code (see below), I see that the server gets the exception only when the client doesn't read anything from the stream. When the client reads from the input stream, no exception is thrown on the server.
can someone please tell me the right way to detect a client side socket close (and also explain the behavior exhibited by the code below)?
Code:
package com.connection;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
public class Test implements Runnable{
ServerSocket ss = null;
public Test() throws Exception{
ss = new ServerSocket(9999);
}
public void run(){
try{
Socket s = ss.accept();
Writer w = new OutputStreamWriter(s.getOutputStream());
w.write("Hello\n");
w.flush();
System.out.println("Server: wrote string 1");
System.out.println("Server: sleeping...");
Thread.sleep(5000);
System.out.println("Server: woke up");
w.write("Hello\n");
w.flush();
System.out.println("Server: wrote string 2");
}catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception{
Thread server = new Thread(new Test());
server.start();
Thread client = new Thread(new TestClient());
client.start();
}
}
class TestClient implements Runnable{
public void run() {
try {
Socket s = new Socket("localhost", 9999);
// Comment out the below 4 lines to see the write exception on server
BufferedReader r = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println("Client: reading input...");
String str = r.readLine();
System.out.println(str);
// Comment the *above* 4 lines to see exception on server
Thread.sleep(1000);
System.out.println("Client: woke up");
s.close();
System.out.println("Client: socket closed");
}catch(Exception e){
e.printStackTrace();
}
}
}