Chat server. Thread issue - java

Hi could somebody help me with this code because I was trying with If statement but is no working. I am not asking to write for me code just point me at something.
The main problem is that every time somebody connect, new thread is made but when he turn off his chat box the tread stays on and is not working as should be. I mean some body make 10 connections himself and nobody else can chat.
import java.net.*;
import java.io.*;
public class myServer {
static ServerSocket server;
static Socket client;
static DataInputStream in;
static DataOutputStream out;
static clientThread t[] = new clientThread[10];
public static void main(String[] args) throws IOException {
System.out.println("Starting Server");
server = new ServerSocket(7555);
System.out.println("Started Server");
while (true) {
client = server.accept();
System.out.println("CONNECTION");
out = new DataOutputStream(client.getOutputStream());
out.writeUTF("Welcome to the chat room");
for (int i = 0; i <= 9; i++) {
if (t[i] == null) {
(t[i] = new clientThread(client, t)).start();
break;
}
}
}
}
}
class clientThread extends Thread {
DataInputStream in;
DataOutputStream out;
static String msg;
Socket client = null;
clientThread t[];
public clientThread(Socket client, clientThread[] t) {
this.client = client;
this.t = t;
}
public void run() {
try {
in = new DataInputStream(client.getInputStream());
out = new DataOutputStream(client.getOutputStream());
boolean tru = true;
while (tru) {
msg = in.readUTF();
System.out.println(msg);
for (int i = 0; i <= 9; i++)
if (t[i] != null) {
t[i].out.writeUTF(msg);
System.out.println(t[i]);
}
}
} catch (IOException e) {
}
}
}

Your problem is not that the thread stays on, but rather that you have no mechanism for marking your client threads as finished. Even though the thread has exited, t[i] will not become null. It will still refer to an instance of a thread--just a "dead" thread.
Here's are two ways to fix it:
Just before your thread exits, mark t[i] = null (where i is the index of the current thread). Note that you'll need to store the value of i in each thread.
Modify clientThread and add private int threadIndex; as a member variable.
Modify clientThread's constructor and add threadIndex as a parameter.
public clientThread(Socket client, clientThread[] t, int threadIndex)
{
this.threadIndex=threadIndex;
//...
}
Right before the closing brace of run, add
synchronized(t){t[this.threadIndex]=null;}
Use an Executor and submit your clientThreads to it. Java's Executors will handle cleaning up threads for you.

Why are you creating 10 threads for only one socket connection? I think you'd want to create a single ClientThread per incoming connection to the chat server. Then add that single ClientThread to a List of active chats. When the chat client terminates the session, then remove the entry from that List. You don't need to pass the Thread instance, or the array of ClientThreads to the constructor of ClientThread because that is itself. Simply pass the Socket instance to ClientThread, and a reference to the ChatServer. If you are trying to create a chat room. Then allow the server to handle sending a message to everyone else:
public class ChatServer {
List<ClientThread> activeParticipants;
public void say( ClientThread author, String message ) {
for( ClientThread current : activeParticipants ) {
if( current != author ) {
current.send( message ); // this method will send a message to that client
}
}
}
}
You'll either need to use two threads, or use InputStream.available() method to check to see if some input is on either System.in or your socket's input stream. That will allow you to read messages coming in as well as allowing a user to type a message at the same time. Blocking on read() method would mean you couldn't see messages until you enter some data or receive data.
Also move the welcome message into the ClientThread so you don't call Socket.getOutputStream() twice using two different DataOutputStreams.

You call method client.getOutputStream() twice, building each time a DataOutputStream. Try to welcome the user directly in the ClientThread.

Related

My java multi-thread (client-server) program throws a NullPointerException when socket object instance is created using the accept() method

I am trying to create a multi-threaded client-server communication program that uses 2 threads to connect to multiple clients (but only 2 at a time).
The characteristics of the program are:
The clients can terminate the communication program from their side but the server thread does not exit.
The threads in the server do not close ServerSocket until the exit condition is fulfilled by the server program, i.e. the server keeps running continuously connecting to various clients if requested.
Every time a client terminates the program only the communication (related) streams are closed.
Now the problem is the line of code where the Socket object is created. After calling the accept() method of ServerSocket object, a NullPointerException is thrown. Any insight as to where I am going wrong would be very helpful.
My Server side code:
class Clientconnect implements Runnable
{
ServerSocket ss;
Socket s;
String n;
int f;
Clientconnect() throws Exception
{
new ServerSocket(776);
new Socket();
}
public void run()
{
n = Thread.currentThread().getName();
while(true) // thread iteration
{
try
{
System.out.println("Thread "+Thread.currentThread().getName()+" is ready to accept a
connection.....");
s = ss.accept(); // ------**The NullPointerException occurs here**
System.out.println("Thread "+Thread.currentThread().getName()+" has accepted a connection:\n----------");
PrintStream ps = new PrintStream (s.getOutputStream());
BufferedReader cl = new BufferedReader (new InputStreamReader (s.getInputStream()));
BufferedReader kb = new BufferedReader (new InputStreamReader (System.in));
String in, out;
ps.println("you are connected via thread "+n);
ps.println("----------------------");
while (true)
{
in = cl.readLine();
if( in.equalsIgnoreCase("system_exit"))
{
break;
}
System.out.println("Client : "+in);
System.out.print("Server "+n+" :");
out = kb.readLine();
ps.println(out);
}
s.close();
ps.close();
cl.close();
System.out.print("do you want to close the server socket\n1:close\n2:continue\nenter");
f = Integer.parseInt(kb.readLine());
if(f == 1)
{
ss.close();
break;
}
else
{
continue;
}
}
catch (Exception e){e.printStackTrace();}
}
}
}
class test2g
{
public static void main (String args[]) throws Exception
{
Clientconnect cc = new Clientconnect();
Thread t1 = new Thread (cc, "t1");
Thread t2 = new Thread (cc, "t2");
t1.start();
t2.start();
}
}
It is a fairly simple communications program with no complex resource accessing or retrieval. I am running the client end on the same machine so it's "localhost".
My client side code is merely a reciprocation of the try{} block.
P.S. I have tried declaring the ServerSocket & Socket objects as static in the Clientconnect class but it did not help.
I believe ss needs to be assigned in the constructor:
Clientconnect() throws Exception
{
ss = new ServerSocket(776);
new Socket(); // Not needed because it creates a Socket that is immediately thrown away.
}

Thread hanging when calling LinkedList.add

So I'm writing two ServerSockets. One that listens for HTTP requests on port 8085 and saves the byte input into a static LinkedList, and a second that listens on port 8086 and returns all the results in the static LinkedList.
The issue is that when saving the data from ServerSocket:8085 to the LinkedList, the thread hangs and I'm not sure why.
This is the main Listener class:
import java.net.ServerSocket;
import java.nio.charset.Charset;
import java.util.*;
public class Listener {
public static LinkedList<byte[]> Calls = new LinkedList<>();
public static void main(String[] args) {
Thread callback = new Thread(new ThreadListener());
callback.start();
while (true) {
try (var listener = new ServerSocket(8086)) {
System.out.println("Listening on 8086...");
try (var client = listener.accept()) {
StringBuffer response = new StringBuffer();
response.append("HTTP/1.1 200 OK\r\n\r\n");
Iterator<byte[]> iterator = Calls.iterator();
while (iterator.hasNext()) {
response.append(new String(iterator.next(), Charset.forName("UTF-8")) + "\r\n");
iterator.remove();
}
client.getOutputStream().write(response.toString().getBytes("UTF-8"));
client.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
This is the ThreadListener class:
import java.io.IOException;
import java.net.ServerSocket;
import java.util.Date;
public class ThreadListener implements Runnable {
#Override
public void run() {
while (true) {
try (var listener = new ServerSocket(8085)) {
System.out.println("Listening on 8085...");
try (var socket = listener.accept()) {
if (!socket.getInetAddress().getHostAddress().equals("127.0.0.1")) {
System.out.println("Not localhost");
} else {
System.out.println("Its us!");
}
Listener.Calls.add(socket.getInputStream().readAllBytes());
System.out.println("Result collected");
Date today = new Date();
String httpResponse = "HTTP/1.1 200 OK\r\n\r\n" + today;
socket.getOutputStream().write(httpResponse.getBytes("UTF-8"));
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
As for my test, I tried calling 127.0.0.1:8085, and I get an ERR_CONNECTION_RESET, and all I have in the console is the following:
Listening on 8085...
Listening on 8086...
Its us!
Process finished with exit code -1 (I killed the app after 2 mins)
The fact that the "Its us!" message got printed, but the "Results collected!" right after the LinkedList.add didn't is what leads me to assume the LinkedList.add is the one hanging the thread.
Regards
EDIT: No one is calling to 8085 (or 8086), I'm doing it manually on my browser. I solved the Syncronization issue by creating a method to call instead of calling the LinkedList.add directly:
public static synchronized void addElementsToList(byte[] bytes) {
Calls.add(bytes);
}
This does work, but calling the 8085 socket gives the connection reset every time.
Your test mechanism of using a browser to create the request is probably also not helping here, as the InputStream.readAllBytes()
blocks until all remaining bytes have been read and end of stream is detected, or an exception is thrown. This method does not close the input stream.
From the documentation. Specifically, the browser is keeping the connection open, because it's expecting some response. Your server is trying to read everything from the connection until the connection is closed. Catch 22 (aka deadlock).
Try making the connection to localhost:8085 using telnet and closing the connection from the client end.
telnet 127.0.0.1 8085
^D
where ^D is literally the [CTRL] and [D] keys (eg: logout)
A LinkedList is not synchornized, as highlighted in the documentation.
You can either handle synchronisation manually, use a synchronised list, or a concurrent list. Probably some other methods too, but for now, just keep it simple.
public static LinkedList<byte[]> Calls = Collections.synchronizedList(new LinkedList<>());
// or
public static LinkedList<byte[]> Calls = new CopyOnWriteArrayList<>();

server not accepting morethan one client in nio

Am trying to build a chat application.i have a code that sends the data from client to server. when one or more client login(when the client program runs one or more time).server will not accepting the rest of connection other than first connected.
please help me to resolve this
here is my code:
public class Server
{
//Creating non blocking socket
public void non_Socket() throws Exception {
ServerSocketChannel ssChannel = ServerSocketChannel.open();
int port = 80;
int i=0;
ssChannel.socket().bind(new InetSocketAddress(port));
ssChannel.configureBlocking(false);
while(true)
{
SocketChannel sc = ssChannel.accept();`
if (sc == null)
{
System.out.println("Socket channel is null");
Thread.sleep(5000);
}
else
{
System.out.println("Socket channel is not null");
System.out.println("Received an incoming connection from " +
sc.socket().getRemoteSocketAddress());
new PrintRequest(sc,i).start();
i++;
}
}
}
public static void main(String [] abc) throws Exception
{
new Server().non_Socket();
}
}
class PrintRequest extends Thread {
public PrintRequest(SocketChannel sc,int i) throws Exception
{
WritableByteChannel wbc = Channels.newChannel(System.out);
ByteBuffer b = ByteBuffer.allocateDirect(1024); // read 1024 bytes
int numBytesRead = sc.read(b);
while (numBytesRead != -1)
{
b.flip();
while (b.hasRemaining())
{
wbc.write(b);
System.out.println();
//System.out.println("Stream "+i);
// System.out.println(" KKK "+b.toString());
}
//b.clear();
}
}
}
Client code:
public class Client extends Thread {
public void non_Client_Socket() throws Exception
{
SocketChannel sChannel = SocketChannel.open();
sChannel.configureBlocking(false);
sChannel.connect(new InetSocketAddress("localhost", 80));
while (!sChannel.finishConnect())
{
System.out.println("Channel is not connected yet");
}
System.out.println("Channel is ready to use");
/* ---------- going to send data to server ------------*/
System.out.println("please enter the text");
BufferedReader stdin=new BufferedReader(new InputStreamReader(System.in));
while(true)
{
System.out.println("Enter the text");
String HELLO_REQUEST =stdin.readLine().toString();
if(HELLO_REQUEST.equalsIgnoreCase("end"))
{
break;
}
System.out.println("Sending a request to HelloServer");
ByteBuffer buffer = ByteBuffer.wrap(HELLO_REQUEST.getBytes());
sChannel.write(buffer);
}
}
/* ---------- the data is written to sChannel server
will read from this channel ------------ */
public static void main(String [] args) throws Exception
{
new Client().non_Client_Socket();
}
}
There are numerous issues here.
You are putting your ServerSocketChannel into non-blocking mode and then calling accept() without using a Selector. That means 99.9999% of the time accept() will return null, so you are burning CPU cycles. This is pointless. Either accept in blocking mode or use a Selector.
You are putting your client SocketChannel into non-blocking mode, calling connect(), and the calling finishConnect() without using a Selector. That means 99% of the time finishConnect() will return false, so you are burning CPU cycles. This is pointless. Either connect in blocking mode or use a Selector.
You are ignoring the result of SocketChannel.write(). You can't do that. It returns information you need to know about.
In short, your code doesn't make much sense.
I don't have time to look into your code in detail, but some initial observations:
When using NIO, I suggest you use Selector (as I suggested in your previous question) instead of one thread per client.
Remember to bind each client in order to allow the server socket to accept new connections.

Java multiplayer server blocking io

I am currently developing a prototype for a game and I need a simple server to run it.
At this stage, I don't want to invest the time learning about all the different full-featured multiplayer game servers already there (smartfox, etc...)
I know how to develop a basic Server with Threads listening on Sockets but I have ran into a roadblock. Here's the run() function of the Thread
public void run() {
try {
out = new PrintWriter(mSocket1.getOutputStream(), true);
in = new BufferedReader( new InputStreamReader( mSocket1.getInputStream() ) );
String inputLine1 = null, outputLine;
out.println("hello");
out.flush();
while( (inputLine1 = in.readLine()) != null) {
outputLine = mGameControl.processInput(mPlayerNum, inputLine1);
out.println(outputLine);
out.flush();
if(outputLine.contentEquals("bye"))
break;
}
Terminate();
}
catch(IOException e) { e.printStackTrace(); }
}
Now my problem is that the thread is blocked waiting for input. I do have other similar Threads connected to other client which may result in information being dispatched to all clients...
How can I modify it so that a different Thread can interact with it and push info to the client?
Just write a synchronised public method which writes to your PrintWriter, and allow other threads to use it to send messages to your client. Call the same method from your read loop to avoid two threads writing at the same time.
Here's a tested example:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketTest {
public static class Client implements Runnable {
private final BufferedReader in;
private final PrintWriter out;
public Client(Socket clientSocket) throws IOException {
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader( new InputStreamReader( clientSocket.getInputStream() ) );
}
public void run() {
send("Hello");
String inputLine1 = null, outputLine;
try {
while( (inputLine1 = in.readLine()) != null) {
outputLine = inputLine1.toLowerCase();
System.out.println(inputLine1);
send(outputLine);
if(outputLine.contentEquals("bye"))
break;
}
} catch (IOException e) {
e.printStackTrace();
}
}
public synchronized void send(String message) {
out.println(message);
out.flush();
}
}
public static void main(String[] args) throws IOException, InterruptedException {
ServerSocket s = new ServerSocket(5050);
Socket clientSocket = s.accept();
Client client = new Client(clientSocket);
Thread clientThread = new Thread(client);
clientThread.start();
int i = 1;
while (true) {
Thread.sleep(1000);
client.send("Tick " + (i++));
}
}
}
Use Netty to handle your connections and query treatments. Since I discovered that project, I never touched sockets directly anymore (except when writing C programs, etc.)
There are actually some examples to look at and the documentation is quite extensive. The project is very well alive since a couple of years already, and is not soon to die! There's a fairly large user base behind it.
If you only need to perform a non-blocking read on the socket, one of the simplests ways is to use available(). Call available and if there is data to read (bytes pending > 0), perform the read, any way, wait using Thread.sleep() and try to read again. This allow the thread to do while waiting for input data and cat react to external signals.
The use of selectors is encouraged when you need to perform high-performance non-blocking read using one thread and several sockets (java.nio.channels.Selector).

Sockets, Threads and Services in android, how to make them work together?

I am facing a probleme with threads and sockets I cant figure it out, if someone can help me please i would really appreciate.
There are the facts :
I have a service class NetworkService, inside this class I have a Socket attribute.
I would like it be at the state of connected for the whole lifecycle of the service.
To connect the socket I do it in a thread, so if the server has to timeout, it would not block my UI thread.
Problem is, into the thread where I connect my socket everything is fine, it is connected and I can talk to my server, once this thread is over and I try to reuse the socket, in another thread, I have the error message Socket is not connected.
Questions are :
- Is the socket automatically disconnected at the end of the thread?
- Is their anyway we can pass back a value from a called thread to the caller ?
Thanks a lot,
Here is my code
public class NetworkService extends Service {
private Socket mSocket = new Socket();
private void _connectSocket(String addr, int port) {
Runnable connect = new connectSocket(this.mSocket, addr, port);
new Thread(connect).start();
}
private void _authentification() {
Runnable auth = new authentification();
new Thread(auth).start();
}
private INetwork.Stub mBinder = new INetwork.Stub() {
#Override
public int doConnect(String addr, int port) throws RemoteException {
_connectSocket(addr, port);
_authentification();
return 0;
}
};
class connectSocket implements Runnable {
String addrSocket;
int portSocket;
int TIMEOUT=5000;
public connectSocket(String addr, int port) {
addrSocket = addr;
portSocket = port;
}
#Override
public void run() {
SocketAddress socketAddress = new InetSocketAddress(addrSocket, portSocket);
try {
mSocket.connect(socketAddress, TIMEOUT);
PrintWriter out = new PrintWriter(mSocket.getOutputStream(), true);
out.println("test42");
Log.i("connectSocket()", "Connection Succesful");
} catch (IOException e) {
Log.e("connectSocket()", e.getMessage());
e.printStackTrace();
}
}
}
class authentification implements Runnable {
private String constructFirstConnectQuery() {
String query = "toto";
return query;
}
#Override
public void run() {
BufferedReader in;
PrintWriter out;
String line = "";
try {
in = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
out = new PrintWriter(mSocket.getOutputStream(), true);
out.println(constructFirstConnectQuery());
while (mSocket.isConnected()) {
line = in.readLine();
Log.e("LINE", "[Current]- " + line);
}
}
catch (IOException e) {e.printStackTrace();}
}
}
Define the output stream as a member variable, attach it in your thread, and only close that stream when you're done...
Currently you're opening (and implicitly closing) the output stream within the thread. As the thread dies, it will close that output stream, which in turn may be killing the socket/connection.
If you define the stream outside of the thread, you can attach it within the thread, and close it at a later time such as when the service is asked to terminate.

Categories