Server Socket code in linux server - java

I want to know about my socket code and how will it affect my server hardware and other software
I have a linux server with static IP address.
I want to send data from lot of clients to this server using sockets
This is my server side code for the socket
import java.io.DataInputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerSocketExample implements Runnable {
public static void main(String[] args) {
ServerSocketExample start = new ServerSocketExample();
start.run();
}
#Override
public void run() {
try {
ServerSocket ss = new ServerSocket(6664);
Socket s = ss.accept();
DataInputStream dis = new DataInputStream(s.getInputStream());
String str = (String) dis.readUTF();
System.out.println("This: 1: "+str);
if (str != null && !str.trim().equals("")) {
processData(str);
}
s.close();
ss.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
run();
}
}
private void processData(String data) {
System.out.println("This: 3: " + data);
}
}
I want to know how this code may backfire me. Will this affects the server in any way?
Is there any better alternative?
Is this a better option?
Class 1.
import java.io.IOException;
import java.net.ServerSocket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class NetworkService implements Runnable {
private final ServerSocket serverSocket;
private final ExecutorService pool;
public NetworkService(int port, int poolSize) throws IOException {
serverSocket = new ServerSocket(port);
pool = Executors.newFixedThreadPool(poolSize);
}
public void run() {
try {
while (true) {
pool.execute(new Handler(serverSocket.accept()));
}
} catch (IOException ex) {
pool.shutdown();
}
}
}
Class 2.
import java.io.DataInputStream;
import java.net.Socket;
class Handler implements Runnable {
private final Socket socket;
Handler(Socket socket) {
this.socket = socket;
}
public void run() {
try {
DataInputStream dis = new DataInputStream(socket.getInputStream());
String str = (String) dis.readUTF();
System.out.println("This: 1: "+str);
processData(str);
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private void processData(String data) {
System.out.println("This: " + data);
}
}

If you are trying to make a server that takes in multiple clients you have 2 choices. Learn about multi threaded applications or learn about using a selector in the java.nio library.
How to use a selector for multiple users
Multiple thread application
I personally recommend the selector, it is more advanced but it takes less resources which will make it easier for your server.
Hope this helps.

Your class 1 is an issue, your class 2 is mostly correct.
Your issues in class 1 include:
You only need 1 ServerSocket to receive all the client Sockets
public class NetworkService{
static final int PORT = 1978;
public static void main(String args[]) {
ServerSocket serverSocket = null;
Socket socket = null;
try {
serverSocket = new ServerSocket(PORT);
} catch (IOException e) {
e.printStackTrace();
}
while (true) {
try {
socket = serverSocket.accept();
} catch (IOException e) {
System.out.println("I/O error: " + e);
}
// new thread for a client
new Handler(socket).start();
}
}
}
If you want to make it a separate class by all means, that implements Runnable I don't suggest it but by all means.
I have never worked with DataInputStream for reading and writing to using a socket I use BufferedReader for reading & PrintWriter for writing. For use on how to do this oracle gave a tutorial on sockets. This is an example of a server with BufferedReader and PrintWriter

Related

Client-Server communication via XML (Java, TCP)

i have written a client - server programm, where different clients and server communicate via request/reply using xml and tcp sockets. Later i want to add udp sockets. This is the current code:
Client:
package network.client;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class Client implements Closeable {
private Socket socket;
public Client(String host, int port) throws IOException {
this(new Socket(host, port));
}
public Client(Socket s) {
this.socket = s;
}
#Override
public void close() throws IOException {
this.socket.close();
}
public void send(String msg) throws IOException {
OutputStream out=this.socket.getOutputStream();
out.write(msg.getBytes());
out.flush();
socket.shutdownOutput();
}
public void recv() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String request="";
String temp=in.readLine();
while(temp!=null) {
request+=temp;
temp=in.readLine();
}
socket.shutdownInput();
System.out.println("Client: " + request);
System.out.println(request.toString().length());
} catch (IOException ex) {
System.err.println("Error: Unable to read server response\n\t" + ex);
}
}
public static void main(String[] args) {
// Make sure command line arguments are valid
String ip="127.0.0.1";
int port=5000;
StringBuilder sb = new StringBuilder();
sb.append("stuff");
System.out.println(sb.toString().length());
try (Client c = new Client(ip, port)) {
c.send(sb.toString());
c.recv();
c.close();
} catch (IOException ex) {
System.err.println("Error: " + ex);
}
}
}
Server:
package network.server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Server {
private static ServerSocket serversocket;
private static ExecutorService threadpool;
private String ip;
private int port;
public static void main(final String[] args) {
Server2 server;
String ip = "127.0.0.1";
int port = 5000;
try {
server = new Server(ip, port);
while (true) {
Runnable requestHandler = null;
try {
requestHandler = new TCPRequestHandler(serversocket.accept());
} catch (IOException io) {
System.out.println("Accepting client connection failed");
io.printStackTrace();
}
threadpool.submit(requestHandler);
}
} catch (IOException io) {
System.out.println(io.getMessage());
io.printStackTrace();
}
System.out.println("end");
}
public Server(String ip, int port) throws IOException {
this.ip = ip;
this.port = port;
try {
this.serversocket = new ServerSocket();
serversocket.bind(new InetSocketAddress(ip, port));
} catch (IOException io) {
throw new IOException("Creating the ServerSocket failed");
}
System.out.println("Binding the server succeeded");
this.threadpool = Executors.newCachedThreadPool();
}
}
RequestHandler:
public class TCPRequestHandler extends Thread{
private Socket clientSocket=null;
public TCPRequestHandler(Socket clientSocket) {
this.clientSocket=clientSocket;
}
public void run(){
System.out.println("Accepted client connection (" + clientSocket.getInetAddress().getHostAddress() + ", " + clientSocket.getPort() + ")");
byte[] buffer = new byte[1024];
int count;
try {
BufferedReader in =new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
OutputStream out = clientSocket.getOutputStream();
String request="";
String temp=in.readLine();
while(temp!=null) {
request+=temp;
temp=in.readLine();
}
System.out.println("Server:" + request);
System.out.println(request.toString().length());
// do stuff with xml request
out.write(request.getBytes());
out.flush();
clientSocket.shutdownInput();
clientSocket.shutdownOutput();
} catch (IOException io) {
System.err.println("IO initialization failed");
}
}
}
XML Request:
<Request>
<Info Attribute1="" Attribute2=""></Info>
<Info Attribute1="" Attribute2=""></Info>
</Request>
XML Reply (the overhead sending back the attributes will be necessary for the client, so i have to send it twice):
<Reply>
<Info Attribute1="" Attribute2="">GoodReply</Info>
<Info Attribute1="" Attribute2="">GoodReply</Info>
</Reply>
My question is 2-folded:
1.) Maybe I did something unusual at the client-server programming (forgetting to close something, unusual stream reading/handling). Reading every line of the client/server message seems to be e.g. weird for me, because i'd rather read the xml message until it is finished independently of its line). Feel free to provide me "good coding style" advice :-)
2.) At the moment i would assemble the XML by a StringBuilder and send just the bytes of the whole String and without special characters like \r \n. I'm not sure how to do it with a common api like Stax (this seemed to be complicated). Parsing the Attributes and their content will be necessary for the application. Is there an easier/more common way to solve this?
If not: how to do it with e.g Stax?
Good question!
Since TCP is a streaming protocol, you don't really know where the message begins and where it ends, unless you specify that each connect/disconnect contains exactly one message, or that you specify some delimiting mechanism (a framing protocol). Actually, it might be easier to start with UDP, since a datagram could contain the entire message in itself.
As for the framing protocol, an example is the Using the NETCONF Protocol over Secure Shell specification. You can of course devise your own framing.

Java sockets application with two listeners hanging

I'm running a client and server on my local machine and trying to send text messages between the two. Both sides are able to read and write. I'm using ObjectInputStream and ObjectOutputStream because I need to serialize objects. Github repo
My issue is when I try to send messages from both sides, they don't get through to the other side and the listeners hang.
Host.java
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Host {
private ServerSocket serverSocket;
private Socket clientSocket;
private ObjectOutputStream out;
private ObjectInputStream in;
private int portNumber = Settings.PORT;
public Host() {
acceptConnection();
CommandListener commandListener = new CommandListener(in);
}
private void acceptConnection() {
try {
serverSocket = new ServerSocket(portNumber);
clientSocket = serverSocket.accept();
out = new ObjectOutputStream(clientSocket.getOutputStream());
in = new ObjectInputStream(clientSocket.getInputStream());
} catch (IOException e) {
System.out.println("Exception caught when trying to listen on port "
+ portNumber + " or listening for a connection");
System.out.println(e.getMessage());
}
}
public ObjectOutputStream getOut() {
return out;
}
public ObjectInputStream getIn() {
return in;
}
}
Client.java
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
private int portNumber = Settings.PORT;
private ObjectOutputStream out;
private ObjectInputStream in;
private Socket clientSocket;
public Client(String ip) {
connectToHost(ip);
CommandListener commandListener = new CommandListener(in);
}
public ObjectOutputStream getOut() {
return out;
}
public ObjectInputStream getIn() {
return in;
}
private void connectToHost(String ip) {
try {
clientSocket = new Socket(ip, portNumber);
out = new ObjectOutputStream(clientSocket.getOutputStream());
in = new ObjectInputStream(clientSocket.getInputStream());
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + ip);
e.printStackTrace();
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to " + ip);
e.printStackTrace();
}
}
}
The CommandListener.java class is a thread which is started independently by both the client and the server.
import java.io.IOException;
import java.io.ObjectInputStream;
public class CommandListener implements Runnable{
private ObjectInputStream in;
public CommandListener(ObjectInputStream in) {
this.in = in;
run();
}
public void run() {
String inboundCmd;
try {
System.out.println("listener running, waiting for inbound command");
inboundCmd = (String) in.readObject();
System.out.println("listener read inbound command" + inboundCmd);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Both hang after printing out listener running, waiting for inbound command.
Here's how I start the client and the server:
RunHost.java
import java.io.IOException;
import java.io.ObjectOutputStream;
public class RunHost {
public static void main(String[] args) throws IOException {
Host host = new Host();
ObjectOutputStream out = host.getOut();
out.writeObject("host sending");
out.flush();
}
}
RunClient.java
import java.io.IOException;
import java.io.ObjectOutputStream;
public class RunClient {
public static void main(String[] args) throws IOException {
Client client = new Client("localhost");
ObjectOutputStream out = client.getOut();
out.writeObject("client sending");
out.flush();
}
}
Any idea how to fix this?
The reason why it seems like both the host and the client are "hanging" is simply because nobody managed to write anything before listening to the other party.
You should be running RunHost.java before RunClient.java. Starting from there, you can trace the program:
Construct a new Host (i.e. RunHost.java is ran)
Blocks and wait for a client socket to connect
Construct a new Client (i.e. RunClient.java is ran)
Both ServerSocket's and ClientSocket's input and output streams are initialised
Both ServerSocket and ClientSocket start constructing CommandListener
Both ServerSocket and ClientSocket start listening for an input
See the problem yet? The main issue is because you call the method run() within the CommandListener constructor, so both Server and Client side start to block on listening without anyone having sent anything.
A quick fix would be to take out the run() call from the CommandListener constructor function, and then call it separately when you are ready for it.
For example:
Change the constructor in CommandListener.java to:
public CommandListener(ObjectInputStream in) {
this.in = in;
}
Add a way to get the CommandListener for the client in Client.java (note that this means you should store the CommandListener by doing cl = new CommandListener(in); in the Client constructor):
public CommandListener getCL() {
return cl;
}
Change RunClient.java to something like:
public static void main(String[] args) throws IOException {
Client client = new Client("localhost");
ObjectOutputStream out = client.getOut();
out.writeObject("client sending");
out.flush();
CommandListener cl = client.getCL();
cl.run();
}
And lastly, call CommandListener's run() method in Host's constructor:
public Host() {
acceptConnection();
CommandListener commandListener = new CommandListener(in);
commandListener.run();
}
And it should work as per expected.
But to be honest, given the mess that CommandListener is causing, you may want to reconsider having that class in the first place. I mean, over here it doesn't seem to be necessary, so...
P/S Feel free to let me know if anything is unclear/ it still does not work

Java Concurrent Socket Programming

Below is my code for a simple Concurrent Server. Whenever I run multiple clients, the server only prints out the input of the first client. I'm not sure what I've done wrong. Any help would be appreciated.
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8001);
while (true){
Socket clientSocket = serverSocket.accept();
System.out.println(clientSocket);
ConcurrentServer client = new ConcurrentServer(clientSocket);
client.start();
}
} catch (IOException i){}
}
public void run(){
try {
inputStream = new BufferedReader(new InputStreamReader(concurrentSocket.getInputStream()));
outputStream = new PrintWriter(new OutputStreamWriter(concurrentSocket.getOutputStream()));
String testString = inputStream.readLine();
System.out.println(testString);
} catch (IOException i){}
}
This code might help you to understand how to run multiple clients concurrently. :)
What this code does? TCP Client sends a string to the server and TCP server sends back the string in UPPERCASE format & the server can do this concurrently with multiple connections.
I have included 3 files for the server and one more for testing the server with multiple clients(ClientTest.java)
Main.java
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try {
new Server(3000).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Server.java
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Logger;
public class Server {
private ServerSocket sSocket;
private boolean run;
private int port;
public Server(int port) throws IOException {
this.port = port;
this.sSocket = new ServerSocket(this.port);
}
public void start() {
this.run = true;
Logger.getLogger(getClass().getName()).info("Server is listening on port: " + port);
try {
while (run) {
Socket cs = sSocket.accept();
Logger.getLogger(getClass().getName())
.info("New Client Connected! " + cs.getPort());
new Thread(new Client(cs)).start(); // Put to a new thread.
}
} catch (IOException e) {
Logger.getLogger(getClass().getName()).severe(e.getMessage());
}
}
public void stop() {
this.run = false;
}
}
Client.java (Client Process on server)
import java.io.*;
import java.net.Socket;
import java.util.logging.Logger;
public class Client implements Runnable {
private Socket clientSocket;
private DataOutputStream out; // write for the client
private BufferedReader in; // read from the client
public Client(Socket clientSocket) {
this.clientSocket = clientSocket;
}
#Override
public void run() {
// Do client process
outToClient(inFromClient().toUpperCase());
closeConnection();
}
private String inFromClient() {
String messageFromClient = "";
/*
* Do not use try with resources because once -
* - it exits the block it will close your client socket too.
*/
try {
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
messageFromClient = in.readLine();
} catch (IOException e) {
Logger.getLogger(getClass().getName()).severe("InFromClientErr - " + e.getMessage());
}
return messageFromClient.trim().equals("") ? "No Inputs given!" : messageFromClient;
}
private void outToClient(String message) {
try {
out = new DataOutputStream(clientSocket.getOutputStream());
out.writeBytes(message);
} catch (IOException e) {
Logger.getLogger(getClass().getName()).severe("OutToClientErr - " + e.getMessage());
}
}
private void closeConnection() {
try {
in.close();
out.close();
clientSocket.close();
} catch (NullPointerException | IOException e) {
Logger.getLogger(getClass().getName()).severe(e.getMessage());
}
}
}
ClientTest.java (For Testing clients)
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class ClientTest {
public static void main(String[] args) {
Socket clientSocket;
try {
clientSocket = new Socket("localhost", 3000);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
outToServer.writeBytes(new Scanner(System.in).nextLine() + '\n'); // Get user input and send.
System.out.println(inFromServer.readLine()); // Print the server response.
} catch (IOException e) {
e.printStackTrace();
}
}
}
The issue was instead with the client. Not the server. The socket was declared outside of the for loop, and therefore only one connection was being created. Like so below:
public static void main(String[] args) {
try {
socket = new Socket("127.0.0.1", 8001);
for (int i = 0; i < 5; i++){
System.out.println("Starting client: " + i);
ConcurrentClient concurrentClient = new ConcurrentClient(socket, i);
concurrentClient.run();
}
} catch (IOException io) {
}
}
The Socket should be declared inside the for loop like so:
public static void main(String[] args) {
try {
for (int i = 0; i < 5; i++){
socket = new Socket("127.0.0.1", 8001);
System.out.println("Starting client: " + i);
ConcurrentClient concurrentClient = new ConcurrentClient(socket, i);
concurrentClient.run();
}
} catch (IOException io) {
}
}
I really don't know why you need so complex structure of input and output streams. It is better to use Scanner that will wait for the new input.
Also you can use PrintWriter to output the results of your conversation.
Here is server that accepts multiple clients:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class ConcurrentServer extends Thread {
private Socket concurrentSocket;
public ConcurrentServer(Socket clientSocket) {
this.concurrentSocket = clientSocket;
}
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8001);
while (true){
Socket clientSocket = serverSocket.accept();
System.out.println(clientSocket);
ConcurrentServer client = new ConcurrentServer(clientSocket);
client.start();
}
} catch (IOException i){}
}
public void run(){
try {
InputStream inputStream = concurrentSocket.getInputStream();
Scanner scanner = new Scanner(inputStream);
OutputStream outputStream = concurrentSocket.getOutputStream();
PrintWriter pw = new PrintWriter(outputStream);
while(scanner.hasNextLine()){
String line = scanner.nextLine();
System.out.println(line);
pw.println("message: " + line);
pw.flush();
}
} catch (IOException i){}
}
}

java.net.SocketException: Socket is closed between Socket.accept() and Socket.getInputStream()

I'm trying to create a client/server connection and am still quite new to java as well. So the error I am getting tells me that the socket is closed. Following some work, I've managed to write the given code below. I do believe there is something wrong with the way I pass the socket to the connection class, if I had to guess, that causes the socket object to possibly be closed?
I've tried adding waits just in case the server thread hadn't been executed but that didn't seem to affect anything. Maybe I should launch the server with its own launcher in its own command prompt, but I thouht this should work just fine to test the client and server.
I can't seem to find out why my socket is closed before I send my message. Any insights would be greatly appreciated!
Thanks!
Error
java.net.SocketException: Socket is closed
at java.net.Socket.getInputSTream(Unknown Source)
at Connection.run(Connection.java:17)
Server.java
//main calling snippet.
import java.lang.Thread;
public class Server {
public static void main(String[] args) {
if(args.length != 1) {
System.err.println("Usage: java Server <port number>");
System.exit(1);
}
int port = Integer.parseInt(args[0]);
Thread server = new KServer(port);
server.start();
//added waits just to make sure the thread was executed?
//thinking this might be my problem
long t = System.currentTimeMillis() + 5000;
while (System.currentTimeMillis() < t) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
KClient client = new KClient("127.0.0.1",port);
while (!(client.openConn())) {
System.out.println("Failed to connect. Retrying...");
}
client.send("Hello World");
client.closeConn();
}
}
KServer.java
//the actual server class that manages listening and threading the sockets
import java.net.*;
import java.io.*;
public class KServer extends Thread {
private int port;
private ServerSocket sSock;
public KServer(int thisPort) {
port = thisPort;
try {
sSock = new ServerSocket(port);
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
while(true) {
try (Socket cSock = sSock.accept();) {
Thread con = new Connection(cSock);
con.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Connection.java
//Manages sending and receiving messages
import java.net.Socket;
import java.io.*;
public class Connection extends Thread {
Socket socket;
public Connection(Socket s) {
socket = s;
}
public void run() {
String msg;
BufferedReader in;
try {
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while((msg = in.readLine()) != null) {
System.out.println(msg);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
KClient.java
//manages the clients connection life to the server
import java.net.*;
import java.io.*;
public class KClient {
private Socket sock;
private String dest;
private int port;
private OutputStreamWriter out;
public KClient(String dst,int prt) {
dest = dst;
port = prt;
}
public boolean openConn() {
try {
sock = new Socket(dest,port);
out = new OutputStreamWriter(sock.getOutputStream(),"ISO-8859-1");
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public void send(String msg) {
try {
out.write(msg);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public void closeConn() {
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Don't use try-with-resources to accept the socket. It wil close the accepted socket, which needs to stay open so the handling thread can use it. The handling thread is responsible for closing it.

ask about deliver message between client to client

hi i writ acode for client and for server and now i want to deliver the message between clint one to clint two and i dont succees to do this on server side i want to construct array for name and id and after i send message from the client side i can choose where or Which name the server deliver the message pleas help me to writ this
so this is the clint side
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class client {
public static void main(String[] args) {
Socket socket = null;
try {
socket = new Socket("127.0.0.1", 7777);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedReader readerFromCommandLine = new BufferedReader(new InputStreamReader(System.in));
PrintWriter writer = new PrintWriter(socket.getOutputStream());
while(true) {
System.out.println("Say something:");
String userInput = readerFromCommandLine.readLine();
writer.println(userInput);
writer.flush();
String input = reader.readLine();
System.out.println("Got from server: "+input);
if (userInput.equalsIgnoreCase("bye")) {
break;
}
}
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
finally {
if (socket != null) {
try {
socket.close();
}
catch (Exception e) {
System.err.println(e);
e.printStackTrace();
}
}
}
}
}
so now my code shuold by look like this ?
becaus i not yet can send from one client to client two
import java.awt.List;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class server {
public static void main(String[] args) {
ArrayList<Channel> my_clients = new ArrayList<Channel>();
ServerSocket ss = null;
try {
ss = new ServerSocket(7777);
while (true) {
//wait for a new client call - once got it, get the socket for
//that channel
System.out.println("Waiting for an incoming call");
Socket client = ss.accept();
Channel my_new_client = new Channel(client);
my_clients.add(my_new_client);
my_new_client.start();
//once the call has started read the client data
for(Channel my_client : my_clients) {
if(my_client.getName() == "Me") {
//my_client.writer("HELLO!");
}
}
//System.out.println("Accepted a new call");
//new Channel(client).start();
}
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
finally {
if (ss != null) {
try {
ss.close();
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
}
}
}
public static class Channel extends Thread {
private static int clientIndex = 0;
private int index;
private Socket socket = null;
public Channel(Socket socket) {
clientIndex++;
index = clientIndex;
this.socket = socket;
}
#Override
public void run() {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter writer = new PrintWriter(socket.getOutputStream());
while (true) {
String input = reader.readLine();
System.out.println("Got from client "+index+": "+input);
//bye bye
if (input.equalsIgnoreCase("bye")) {
break;
}
writer.println("Gotcha");
writer.flush();
}
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
finally {
if (socket != null) {
try {
socket.close();
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
}
}
}
}
}
String userInput = readerFromCommandLine.readLine();
BufferedReader.readLine() is a problem here. It is going to block your thread until input is received. This means communication can only ever go in one direction at a time, and can potentially get totally blocked if both clients are waiting.
DataFetcher can fix this problem; you can use it to listen in a separate Thread
http://tus.svn.sourceforge.net/viewvc/tus/tjacobs/io/
You half way there.
You created a Threaded Server were each connection from a client opens a thread. This thread then loops and waits for messages.
Think of these threads as you connected clients with their own objects / properties and their streams to write to and read from them.
So each time a clients connections you want to create their thread add it to some kind of list and start their thread. For example:
At the top of the class
List<Channel> my_clients = new List<Channel>();
In your while loop
Channel my_new_client = new Channel(client);
my_clients.add(my_new_client);
my_new_client.start();
Then when you want to send a message to a certain clients. You can loop all the Threads and look for one that has some kind of name or Unique Indentifier. For example:
for(Channel my_client : my_clients) {
if(my_client.getName() == "Me") {
my_client.write("HELLO!");
}
}
or in the same breath you could send a message to all your clients (Broadcast):
for(Channel my_client : my_clients) {
my_client.write("HELLO!");
}
remember to remove the clients when they disconnect too!
// Can't remember the precise exception correct my if I'm wrong!
catch(SocketException ex) {
my_clients.remove(this);
}
Note this expects that you some how authenticate and know the name of your client or supply them a UID which you reference when you are instructed to sent them something. And that the Channel class has the Write Method for connivance.
Hope that Help!

Categories

Resources