Handle streams with multiple clients? - java

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();
}
}
}

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.

Java EchoTCPServer - Send to all clients

Here's my code:
SERVER:
package server;
public class Main {
public static void main(String args[]) {
new EchoServer(9000);
}
}
+
package server;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class EchoServer {
private ServerSocket server;
public EchoServer(int port) {
try {
server = new ServerSocket(port);
while (true) {
Socket socket = server.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println(in.readLine() + " | MOD");
socket.close();
}
} catch(Exception err) {
err.printStackTrace();
}
}
}
CLIENT:
package client;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Main {
public static void main(String args[]) {
try {
while (true) {
Socket socket = new Socket("localhost", 9000);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
out.println(input.readLine());
System.out.println(in.readLine());
socket.close();
}
} catch (Exception err) {
System.out.println(err);
}
}
}
It works all as it should, except that I want when the server sends the "message" + " | MOD" to the client, I want the server to send that to all clients, how can I do that?
I am new to Java, but not to coding so please help me if I've done some wrong stuff that can be done easier or better.
Please help.
Thanks alot.
What you can do is save the client sockets in an array, and then use a for loop to send to each socket.
First, declare your clientSocket array; note that 5 is just an arbitrary size used for testing. Also, declare a counter int.
public Socket clientSocket[] = new Socket[5];
public int intLastSocket = 0;
// this should be placed where you're waiting to accept connections
while (true) {
printTCP("Ready to accept welcome socket");
clientSocket[intLastSocket] = welcomeSocket.accept();
intLastSocket++;
}
// on the server, call this to send. s is a reference to the server object
public void sendToAllTCP(TCPServer s, String message) {
for (Socket z : s.clientSocket) {
if (z != null) {
PrintStream outToClient = null;
try {
outToClient = new PrintStream(z.getOutputStream());
outToClient.println(message);
} catch (IOException e) {
TCPServer.printTCP("Caught an IO exception trying "
+ "to send to TCP connections");
e.printStackTrace();
}
}
}
}
IN YOUR CODE:
package com.murplyx.server;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class EchoServer {
private ServerSocket server;
// use the clientSocket Array to save each new connection
public Socket clientSocket[] = new Socket[5];
public EchoServer(int port) {
try {
server = new ServerSocket(port);
// this should be placed where you're waiting to accept connections
while (true) {
System.out.println("Ready to accept welcome socket");
clientSocket[intLastSocket] = server.accept();
intLastSocket++;
//send your message here, note that putting
//it here will send it each time u add a new connection
sendToAllTCP(/*the message you want to send */);
}
} catch(Exception err) {
err.printStackTrace();
}
}
public void sendToAllTCP(String message) {
// this is an enchanced for loop, i don't know if it's in other languages
// but in java it's supposed to let you loop through
//each object in any iterable list
// such as array, arraylist, linkedlist, etc
for (Socket z : clientSocket) {
if (z != null) {
//basically this chunk of code declares output and input streams
//for each socket in your array of saved sockets
PrintStream outToClient = null;
try {
outToClient = new PrintStream(z.getOutputStream());
outToClient.println(message);
} catch (IOException e) {
System.out.println("Caught an IO exception trying "
+ "to send to TCP connections");
e.printStackTrace();
}
}
}
}
}
Depending on when you want to send your message, you can use the console and sys.in to send it. For example, if you read a line from sys.in and it .equals("sendMsg"), then you can call sendToAllTCP(yourmessage)
You should take a look at multiThreaded chat Server. Each client wich connects gets it's own thread.
Here is the perfect answer to your question:
multithread client-server chat, using sockets
Good luck mate!

Java Server/Client string delay

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.

Java Sockets: My server input stream will not read from the client output stream?

EDIT: Ik it is long but does anyone know how to program sockets??
My problem is confusing me a bit. I have a server running on one computer and on another, I have a client connected to it. When I type a message from the client into the console and send it, the server does not seem to receive it. Anybody know why because I have been testing with printing to the console for the last 3 hours and cannot figure this out. I am relatively new to sockets so don't be too harsh if I am just being an idiot.
Heres my code for the client side:
import java.net.*;
import java.util.Scanner;
import java.io.*;
public class SocketClient {
public static void main(String [] args) {
String host = "************";
int port = 25565;
StringBuffer instr = new StringBuffer();
String TimeStamp;
System.out.println("SocketClient initialized");
try {
InetAddress address = InetAddress.getByName(host);
Socket connection = new Socket(address, port);
BufferedOutputStream bos = new BufferedOutputStream(connection.getOutputStream());
OutputStreamWriter osw = new OutputStreamWriter(bos, "US-ASCII");
Scanner scan = new Scanner(System.in);
String message = scan.nextLine();
TimeStamp = new java.util.Date().toString();
String process = "Server called on " + host + ":" + port + " at " + TimeStamp + ": " + message + (char) 13;
osw.write(process);
osw.flush();
BufferedInputStream bis = new BufferedInputStream(connection.getInputStream());
InputStreamReader isr = new InputStreamReader(bis, "US-ASCII");
int c;
while ( (c = isr.read()) != 13)
instr.append( (char) c);
connection.close();
System.out.println(instr);
} catch (UnknownHostException e) {
System.err.println("UnknownHostException: " + e);
} catch (IOException e) {
System.err.println("IOExcepion: " + e);
}
}
}
Here is the code to connect the client to the server:
import java.io.IOException;
import java.net.*;
public class MultipleSocketServer {
public static Socket connection;
public static String name = "Tyler's Server";
public static int limit = 2;
public static Thread[] clients = new Thread[limit];
public static int current = 0;
public static int port = 25565;
public static String[] connected = {"", ""};
public static ServerSocket socket;
public static void main(String[] args) {
System.out.println("Server starting...");
try {
ServerSocket socket = new ServerSocket(port);
while(true) {
Socket connection = socket.accept();
String ip = connection.getRemoteSocketAddress().toString().substring(1, 13);
loop:
for(int i = 0; i < connected.length; i++) {
if(connected[0].equals(ip) || connected[1].equals(ip)) {
break loop;
}else if(!connected[i].equals(ip)) {
connected[i] = ip;
System.out.println(ip);
MultiServer_Client client = new MultiServer_Client(connection, i);
Thread run = new Thread(client);
run.start();
break loop;
}
}
}
} catch (IOException e1) {
System.out.println("Could not bind server on: " + port);
System.exit(-1);
}
}
}
And here is my code to handle each client as connected:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class MultiServer_Client implements Runnable {
public String time;
public Socket client;
public StringBuffer process = new StringBuffer();
public BufferedInputStream inputStream;
public InputStreamReader reader;
public BufferedOutputStream outputStream;
public OutputStreamWriter writer;
public boolean connected = true;
public int ID;
public MultiServer_Client(Socket connection, int i) {
client = connection;
ID = i;
try {
inputStream = new BufferedInputStream(client.getInputStream());
reader = new InputStreamReader(inputStream);
outputStream = new BufferedOutputStream(client.getOutputStream());
writer = new OutputStreamWriter(outputStream, "US-ASCII");
} catch (IOException e) {
System.out.println("IOException: " + e);
}
System.out.println("Client connected...");
write("Connected to " + MultipleSocketServer.name);
}
public void run() {
while(connected) {
write("hi");
}
System.out.println("Disconnecting client...");
}
public void write(String authen) {
try {
time = new java.util.Date().toString();
String message = time + ": " + authen + (char) 13;
writer.write(message);
writer.flush();
} catch (IOException e) {
connected = false;
MultipleSocketServer.connected[ID] = "";
}
}
public void read() {
//read from client
int character;
process = new StringBuffer();
try {
while ((character = reader.read()) != 13) {
process.append((char) character);
}
System.out.println(process);
process.delete(0, process.length());
} catch (IOException e) {
connected = false;
MultipleSocketServer.connected[ID] = "";
}
}
}
Srry if I cannot help very much. As I said, I am new to sockets and no one else seems to have any problems with this... Thanks :)
The problem with your code is not the "sockets" its your communication protocol. You are effectively closing the socket before the server has a chance to write out "hi".
To debug this, you want to reduce the complexity of your program. There are a number of things that don't make any sense or matter in your program.
So, a little background on Sockets. There are two types of sockets. A "ServerSocket" and a "Socket" The ServerSocket is sort of like a secretary. Its only job is to listen for calls and then pass them on. This is what the "accept" does. Before any client connects, the accept() will block until it receives a connection. Once the client connects, the accept returns a Socket representing the connection.
The regular Socket is where all the work occurs. You can think of it as a telephone connection. You can talk to someone remotely with the OutputStream, and listen using the InputStream. The challenge is that you need to create some sort of communication (called a protocol) for your two sockets to communicate.
You need to figure out how you want to delimit your commands. You could pass a fixed length number and then the data if you want a "length" delimited protocol or you could use a special character for the end of the message (what you currently have). For the quick and dirty, I often use the latter with a newline character. The easiest is to just use a PrintWriter for writing and a Scanner for reading.
The next step is to figure out the communication pattern for the client and the server. Think if it as passing a ball back and forth. If the client says something, the other side should be listening (and vice versa).
Once the protocol and logic is figured out, you can then move the logic for "handling" the server side into separate threads (called a worker pattern) so that the server can handle more than one client at a time. If you want to go even further, you can implement a reactor with a thread pool so that the server doesn't run out of threads, but that is probably for another day/question.
I would recommend following the Java tutorial on Sockets: http://docs.oracle.com/javase/tutorial/networking/sockets/index.html

Java: how to detect in the server, whether a client socket has been closed?

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();
}
}
}

Categories