Java DataInputStream sometimes returns empty - java

I currently am making a messaging application which I will also add encryption to later.
I have a server which opens a socket and waits for clients to connect. Once client connects, it creates a new thread for that client. and then waits for messages etc.
The problem I am having is that when I try to send the public key exponent and modulus to the client, the Client is unable to use datainputstream(clientSocket.getInputStream()).readLine.
The sending of the exponent and Modulus happen on line 173 and 174.The receiving on the client side happens on line 125 and 136.
Server sending the data.
os.println(modulusMap.get(requestName));
os.println(exponentMap.get(requestName));
Client attempting to write the data to a variable:
pubModulusString = is.readLine().trim();
BigInteger pubModulus = new BigInteger(pubModulusString);
HashMap<String, BigInteger> modulusMap = new HashMap<String, BigInteger>();
modulusMap.put(message.substring(1), pubModulus);
String pubExponentString = is.readLine();
I have tested the sending of data as just a print stream and it is working perfectly. It is only when I try to read the data and save it into a variable that the problem occurs(line 125 and 136).
Majority of the time the readLine() reads the modulus as just blank, but sometimes it will successfully read it. I cannot find a pattern to when it is successful and when it is not.
What is also very weird is that I use the exact same code to send data from client to server. This can be seen on Client side line 89 and 91. And the server receives the data on lines 113 and 119.
Thank you for any help or ideas in advance.
Posted below is the full code for any 1 that is kind enough and has the time to run it.
Server:
import java.io.*;
import java.math.*;
import java.net.Socket;
import java.net.ServerSocket;
import java.util.*;
/*
* A chat server that delivers public and private messages.
*/
public class MultiThreadChatServerSync {
// The server socket.
private static ServerSocket serverSocket = null;
// The client socket.
private static Socket clientSocket = null;
// This chat server can accept up to maxClientsCount clients' connections.
private static final int maxClientsCount = 10;
private static final clientThread[] threads = new clientThread[maxClientsCount];
public static void main(String args[]) {
// The default port number.
int portNumber = 2222;
if (args.length < 1) {
System.out.println("Usage: java MultiThreadChatServerSync <portNumber>\n"
+ "Now using port number=" + portNumber);
} else {
portNumber = Integer.valueOf(args[0]).intValue();
}
/*
* Open a server socket on the portNumber (default 2222). Note that we can
* not choose a port less than 1023 if we are not privileged users (root).
*/
try {
serverSocket = new ServerSocket(portNumber);
} catch (IOException e) {
System.out.println(e);
}
/*
* Create a client socket for each connection and pass it to a new client
* thread.
*/
while (true) {
try {
clientSocket = serverSocket.accept();
int i = 0;
for (i = 0; i < maxClientsCount; i++) {
if (threads[i] == null) {
(threads[i] = new clientThread(clientSocket, threads)).start();
break;
}
}
if (i == maxClientsCount) {
PrintStream os = new PrintStream(clientSocket.getOutputStream());
os.println("Server too busy. Try later.");
os.close();
clientSocket.close();
}
} catch (IOException e) {
System.out.println(e);
}
}
}
}
/*
* The chat client thread. This client thread opens the input and the output
* streams for a particular client, ask the client's name, informs all the
* clients connected to the server about the fact that a new client has joined
* the chat room, and as long as it receive data, echos that data back to all
* other clients. The thread broadcast the incoming messages to all clients and
* routes the private message to the particular client. When a client leaves the
* chat room this thread informs also all the clients about that and terminates.
*/
class clientThread extends Thread {
private String clientName = null;
private DataInputStream is = null;
private BufferedReader inputLine = null;
private PrintStream os = null;
private Socket clientSocket = null;
private final clientThread[] threads;
private int maxClientsCount;
public clientThread(Socket clientSocket, clientThread[] threads) {
this.clientSocket = clientSocket;
this.threads = threads;
maxClientsCount = threads.length;
}
public void run() {
int maxClientsCount = this.maxClientsCount;
clientThread[] threads = this.threads;
HashMap<String, BigInteger> modulusMap = new HashMap<String, BigInteger>();
HashMap<String, BigInteger> exponentMap = new HashMap<String, BigInteger>();
try {
/*
* Create input and output streams for this client.
*/
is = new DataInputStream(clientSocket.getInputStream());
os = new PrintStream(clientSocket.getOutputStream());
inputLine = new BufferedReader (new InputStreamReader(System.in));
String name;
while (true) {
os.println("Enter your name.");
name = is.readLine().trim();
String pubModulusString = is.readLine().trim();
BigInteger pubModulus = new BigInteger(pubModulusString);
modulusMap.put(name, pubModulus);
String pubExponentString = is.readLine().trim();
BigInteger pubExponent = new BigInteger(pubExponentString);
exponentMap.put(name, pubExponent);
if (name.indexOf('#') == -1) {
break;
} else {
os.println("The name should not contain '#' character.");
}
}
/* Welcome the new the client. */
os.println("Welcome " + name
+ " to our chat room.\nTo leave enter /quit in a new line.");
synchronized (this) {
for (int i = 0; i < maxClientsCount; i++) {
if (threads[i] != null && threads[i] == this) {
clientName = "#" + name;
break;
}
}
for (int i = 0; i < maxClientsCount; i++) {
if (threads[i] != null && threads[i] != this) {
threads[i].os.println("*** A new user " + name
+ " entered the chat room !!! ***");
}
}
}
/* Start the conversation. */
while (true) {
String line = is.readLine();
if (line.startsWith("/quit")) {
break;
}
if (line.startsWith("!")){
String requestName;
requestName = line;
requestName = requestName.substring(1);
os.println(modulusMap.get(requestName));
os.println(exponentMap.get(requestName));
}
else {
/* If the message is private sent it to the given client. */
if (line.startsWith("#")) {
String[] words = line.split("\\s", 2);
if (words.length > 1 && words[1] != null) {
words[1] = words[1].trim();
if (!words[1].isEmpty()) {
synchronized (this) {
for (int i = 0; i < maxClientsCount; i++) {
if (threads[i] != null && threads[i] != this
&& threads[i].clientName != null
&& threads[i].clientName.equals(words[0])) {
threads[i].os.println("<" + name + "> " + words[1]);
/*
* Echo this message to let the client know the private
* message was sent.
*/
this.os.println(">" + name + "> " + words[1]);
break;
}
}
}
}
}
} else {
/* The message is public, broadcast it to all other clients. */
synchronized (this) {
this.os.println("Please select who you wish to message by typing '#username *Your Message*'");
}
}
}
}
synchronized (this) {
for (int i = 0; i < maxClientsCount; i++) {
if (threads[i] != null && threads[i] != this
&& threads[i].clientName != null) {
threads[i].os.println("*** The user " + name
+ " is leaving the chat room !!! ***");
}
}
}
os.println("*** Bye " + name + " ***");
/*
* Clean up. Set the current thread variable to null so that a new client
* could be accepted by the server.
*/
synchronized (this) {
for (int i = 0; i < maxClientsCount; i++) {
if (threads[i] == this) {
threads[i] = null;
}
}
}
/*
* Close the output stream, close the input stream, close the socket.
*/
is.close();
os.close();
clientSocket.close();
} catch (IOException e) {
}
}
}
Client
import java.io.DataInputStream;
import java.io.*;
import java.math.*;
import java.math.BigInteger;
import java.net.Socket;
import java.net.ServerSocket;
import java.net.UnknownHostException;
import java.security.*;
import java.security.spec.*;
import java.util.*;
import javax.crypto.*;
public class MultiThreadChatClient implements Runnable {
// The client socket
private static Socket clientSocket = null;
// The output stream
private static PrintStream os = null;
// The input stream
private static DataInputStream is = null;
private static BufferedReader inputLine = null;
private static boolean closed = false;
private static final String PUBLIC_KEY_FILE = "Public.key";
private static final String PRIVATE_KEY_FILE = "Private.key";
public static void main(String[] args) {
// The default port.
int portNumber = 2222;
// The default host.
String host = "192.168.0.16";
if (args.length < 2) {
System.out
.println("Usage: java MultiThreadChatClient <host> <portNumber>\n"
+ "Now using host=" + host + ", portNumber=" + portNumber);
} else {
host = args[0];
portNumber = Integer.valueOf(args[1]).intValue();
}
/*
* Open a socket on a given host and port. Open input and output streams.
*/
try {
clientSocket = new Socket(host, portNumber);
inputLine = new BufferedReader(new InputStreamReader(System.in));
os = new PrintStream(clientSocket.getOutputStream());
is = new DataInputStream(clientSocket.getInputStream());
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + host);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to the host "
+ host);
}
/*
* If everything has been initialized then we want to write some data to the
* socket we have opened a connection to on the port portNumber.
*/
if (clientSocket != null && os != null && is != null) {
try {
/* Create a thread to read from the server. */
new Thread(new MultiThreadChatClient()).start();
String myName = inputLine.readLine();
os.println(myName.trim());
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048); //1024 used for normal securities
KeyPair keyPair = keyPairGenerator.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
//Pullingout parameters which makes up Key
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKeySpec rsaPubKeySpec = (RSAPublicKeySpec) keyFactory.getKeySpec(publicKey, RSAPublicKeySpec.class);
RSAPrivateKeySpec rsaPrivKeySpec = (RSAPrivateKeySpec) keyFactory.getKeySpec(privateKey, RSAPrivateKeySpec.class);
os.println(rsaPubKeySpec.getModulus());
System.out.println(rsaPubKeySpec.getModulus());
os.println(rsaPubKeySpec.getPublicExponent());
FileOutputStream fos = null;
ObjectOutputStream oos = null;
fos = new FileOutputStream(PUBLIC_KEY_FILE);
oos = new ObjectOutputStream(new BufferedOutputStream(fos));
oos.writeObject(rsaPubKeySpec.getModulus());
oos.writeObject(rsaPubKeySpec.getPublicExponent());
oos.close();
fos.close();
fos = new FileOutputStream(PRIVATE_KEY_FILE);
oos = new ObjectOutputStream(new BufferedOutputStream(fos));
oos.writeObject(rsaPrivKeySpec.getModulus());
oos.writeObject(rsaPrivKeySpec.getPrivateExponent());
oos.close();
fos.close();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}catch (InvalidKeySpecException e) {
e.printStackTrace();
}
while (!closed) {
String message = inputLine.readLine();
if (message.startsWith("!")){
os.println(message.trim());
String pubModulusString = is.readLine().trim();
BigInteger pubModulus = new BigInteger(pubModulusString);
HashMap<String, BigInteger> modulusMap = new HashMap<String, BigInteger>();
modulusMap.put(message.substring(1), pubModulus);
String pubExponentString = is.readLine();
BigInteger pubExponent = new BigInteger(pubExponentString);
HashMap<String, BigInteger> exponentMap = new HashMap<String, BigInteger>();
exponentMap.put(message.substring(1), pubExponent);
System.out.println(modulusMap.get(message.substring(1)) + " Hi");
System.out.println(exponentMap.get(message.substring(1)) + "asdk");
}
else{
// INSERT ENCRYPTION ON "message" here
os.println(message.trim());
}
}
/*
* Close the output stream, close the input stream, close the socket.
*/
os.close();
is.close();
clientSocket.close();
} catch (IOException e) {
System.err.println("IOException: " + e);
}
}
}
/*
* Create a thread to read from the server. (non-Javadoc)
*
* #see java.lang.Runnable#run()
*/
public void run() {
/*
* Keep on reading from the socket till we receive "Bye" from the
* server. Once we received that then we want to break.
*/
String responseLine;
try {
while ((responseLine = is.readLine()) != null) {
System.out.println(responseLine);
if (responseLine.indexOf("*** Bye") != -1)
break;
}
closed = true;
} catch (IOException e) {
System.err.println("IOException: " + e);
}
}
}

If readLine() returns a blank line, it is because the sender sent a blank line. If it returns null, the sender has closed the connection.
You're looking in the wrong place.

The method readLine of DataInputStream is deprecated. I don't know why you use it, normally if you use an IDE like eclipse you'll see this method crossed out.
You should use a BufferedReader instead as explained in the Java documentation itself, here is a link.

Related

Send to a server using a specific active thread

I have this class where i try to create a number of threads and then i need to send a message to the server over all the threads or using a specific thread. I can't seem to find a way to do that in this way I can only send using the last thread that was created.
Here is the class:
public class test{
public test(){
}
public static void main(String[] args){
MultiThreadChatClient mc = new MultiThreadChatClient();
test st = new test();
for(int i =0; i<=4; i++){
mc.createThreads();
}
while (true) {
System.out.print("type your message: ");
Scanner s = new Scanner(System.in);
String ss = s.nextLine();
ss = ss.trim().replaceAll(" +", " ");
mc.sendMessage(ss);
try
{
Thread.sleep(400);
}
catch(InterruptedException e)
{
// this part is executed when an exception (in this example InterruptedException) occurs
System.out.println("Exeption: " + e);
}
}
}
}
Here's the Client thread class:
public class MultiThreadChatClient implements Runnable {
// The client socket
private static Socket clientSocket = null;
// The output stream
private static PrintStream os = null;
// The input stream
private static BufferedReader br;
private static BufferedReader inputLine = null;
private static boolean closed = false;
public static void main(String[] args) {
// The default port.
int portNumber = 2222;
// The default host.
String host = "localhost";
if (args.length < 2) {
System.out.println("Usage: java MultiThreadChatClient <host> <portNumber>\n"
+ "Now using host=" + host + ", portNumber=" + portNumber);
} else {
host = args[0];
portNumber = Integer.valueOf(args[1]).intValue();
}
}
/*
* Open a socket on a given host and port. Open input and output streams.
*/
public void createThreads(){
try {
clientSocket = new Socket("localhost", 2222);
inputLine = new BufferedReader(new InputStreamReader(System.in));
os = new PrintStream(clientSocket.getOutputStream());
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + 2222);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to the host " + 2222);
}
//}
/*
* If everything has been initialized then we want to write some data to the
* socket we have opened a connection to on the port portNumber.
*/
if (clientSocket != null && os != null && br != null) {
new Thread(new MultiThreadChatClient()).start();
}
}
public void sendMessage(String mes){
os.println(mes);
}
/*
* Create a thread to read from the server. (non-Javadoc)
*
* #see java.lang.Runnable#run()
*/
public void run() {
/*
* Keep on reading from the socket till we receive "Bye" from the
* server. Once we received that then we want to break.
*/
String responseLine;
try {
while ((responseLine = br.readLine()) != null){
System.out.println(responseLine);
if (responseLine.indexOf("*** Bye") != -1)
break;
}
closed = true;
} catch (IOException e) {
System.err.println("IOException1234: " + e);
}
}
}
Here's the server code:
public class MultiThreadChatServerSync {
// The server socket.
private static ServerSocket serverSocket = null;
// The client socket.
private static Socket clientSocket = null;
// This chat server can accept up to maxClientsCount clients' connections.
private static final int maxClientsCount = 50;
private static final clientThread[] threads = new clientThread[maxClientsCount];
public static void main(String args[]) {
// The default port number.
int portNumber = 2222;
if (args.length < 1) {
System.out.println("Usage: java MultiThreadChatServerSync <portNumber>\n"
+ "Now using port number=" + portNumber);
} else {
portNumber = Integer.valueOf(args[0]).intValue();
}
/*
* Open a server socket on the portNumber (default 2222). Note that we can
* not choose a port less than 1023 if we are not privileged users (root).
*/
try {
serverSocket = new ServerSocket(portNumber);
//System.out.println(serverSocket.getPort());
} catch (IOException e) {
System.out.println(e);
}
/*
* Create a client socket for each connection and pass it to a new client
* thread.
*/
while (true) {
try {
clientSocket = serverSocket.accept();
int i = 0;
for (i = 0; i < maxClientsCount; i++) {
if (threads[i] == null) {
(threads[i] = new clientThread(clientSocket, threads)).start();
//System.out.println("A new client is created");
break;
}
}
if (i == maxClientsCount) {
PrintStream os = new PrintStream(clientSocket.getOutputStream());
os.println("Server too busy. Try later.");
os.close();
clientSocket.close();
}
} catch (IOException e) {
System.out.println(e);
}
}
}
}
class clientThread extends Thread {
MultiThreadChatServerSync ms = new MultiThreadChatServerSync();
private String clientName = null;
//private DataInputStream is = null;
private BufferedReader br = null;
private PrintStream os = null;
private Socket clientSocket = null;
private final clientThread[] threads;
private int maxClientsCount;
public clientThread(Socket clientSocket, clientThread[] threads) {
this.clientSocket = clientSocket;
this.threads = threads;
maxClientsCount = threads.length;
//System.out.println("Inside the Client thread");
}
public void run() {
MultiThreadChatServerSync mss = new MultiThreadChatServerSync();
int maxClientsCount = this.maxClientsCount;
clientThread[] threads = this.threads;
//System.out.println("Inside the run");
try {
/*
* Create input and output streams for this client.
*/
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
os = new PrintStream(clientSocket.getOutputStream());
while (true) {
String line = br.readLine();
System.out.println("message received via Client port: " + clientSocket.getPort());
System.out.println("Received: " + line);
}
} catch (IOException e) {
}
}
}
So, is there a way to create 5 threads and then send the message over all of them or choose one specific thread out of them?
To be able to have a client which starts several sessions, and to be able to send data to one or several of them, the client must change in a few ways.
The static references in the client must be removed.
The Socket instances must be created and stored in the main thread (the writers will be used to send messages on behalf of one or more client sessions)
Each client session is now only responsible for reading (the reader is passed via the constructor).
The code is based on your original code, and meant to be a template for further enhancements: It will manage 5 client sessions, and be able to write to 1 or many.
The new main Thread (As an example, the Scanner will first ask the message for client #1, then 2, 3, 4 and next will broadcast to all, in a loop):
public class MultiThreadChatClientRunner {
final int NO_CLIENTS = 5;
//final String HOST_IP = "192.168.2.7";
final String HOST_IP = "localhost";
public static void main(String[] args) {
new MultiThreadChatClientRunner().start();
}
private void start() {
Socket[] sockets = new Socket[NO_CLIENTS];
PrintStream[] writers = new PrintStream[NO_CLIENTS];
BufferedReader[] readers = new BufferedReader[NO_CLIENTS];
for (int i = 0; i < NO_CLIENTS; i++) {
System.out.println("Creating client number "+i);
Socket clientSocket;
try {
clientSocket = new Socket(HOST_IP, 2222);
writers[i] = new PrintStream(clientSocket.getOutputStream());
readers[i] = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
new Thread(new MultiThreadChatClient(i, readers[i])).start();
} catch (IOException e) {
e.printStackTrace();
}
}
int clientId = 0;
Scanner s = new Scanner(System.in);
while (true) {
System.out.print("type your message for client #"+clientId);
String ss = s.nextLine();
ss = ss.trim().replaceAll(" +", " ");
writers[clientId].println(ss);
clientId = (clientId+1)%NO_CLIENTS;
// Test to broadcast to all clients
if (clientId == 4) {
for (int i = 0; i<NO_CLIENTS; i++)
writers[i].println("Broadcast message: "+ss);
}
try {
Thread.sleep(400);
} catch (InterruptedException e) {
System.out.println("Thread was interrupted");
break;
}
}
s.close();
}
}
The new client, which is much simpler than before:
public class MultiThreadChatClient implements Runnable {
// The client socket
private Socket clientSocket = null;
// The output stream
private PrintStream os = null;
// The input stream
private final BufferedReader br;
private final int clientId;
public MultiThreadChatClient(int clientId, BufferedReader br) {
super();
this.clientId = clientId;
this.br = br;
}
/*
* Create a thread to read from the server. (non-Javadoc)
*
* #see java.lang.Runnable#run()
*/
public void run() {
/*
* Keep on reading from the socket till we receive "Bye" from the
* server. Once we received that then we want to break.
*/
String responseLine;
try {
while ((responseLine = br.readLine()) != null) {
System.out.printf("Client #%d received message=%s\n", clientId, responseLine);
if (responseLine.indexOf("*** Bye") != -1)
break;
}
} catch (IOException e) {
System.err.println("IOException1234: " + e);
}
}
}
And the server, which is nearly identical, but manages closes better, and has some more logging to show which client is communicating.
public class MultiThreadChatServerSync {
// The server socket.
private static ServerSocket serverSocket = null;
// The client socket.
private static Socket clientSocket = null;
// This chat server can accept up to maxClientsCount clients' connections.
private static final int maxClientsCount = 50;
private static final ClientThread[] threads = new ClientThread[maxClientsCount];
public static void main(String args[]) {
// The default port number.
int portNumber = 2222;
if (args.length < 1) {
System.out.println(
"Usage: java MultiThreadChatServerSync <portNumber>\n" + "Now using port number=" + portNumber);
} else {
portNumber = Integer.valueOf(args[0]).intValue();
}
/*
* Open a server socket on the portNumber (default 2222). Note that we
* can not choose a port less than 1023 if we are not privileged users
* (root).
*/
try {
serverSocket = new ServerSocket(portNumber);
// System.out.println(serverSocket.getPort());
} catch (IOException e) {
System.out.println(e);
}
/*
* Create a client socket for each connection and pass it to a new
* client thread.
*/
while (true) {
try {
System.out.println("Awaiting a new connection on "+serverSocket.getLocalPort());
clientSocket = serverSocket.accept();
int i = 0;
for (i = 0; i < maxClientsCount; i++) {
if (threads[i] == null) {
(threads[i] = new ClientThread(i, clientSocket)).start();
// System.out.println("A new client is created");
break;
}
}
if (i == maxClientsCount) {
PrintStream os = new PrintStream(clientSocket.getOutputStream());
os.println("Server too busy. Try later.");
os.close();
clientSocket.close();
}
} catch (IOException e) {
System.out.println(e);
}
}
}
}
class ClientThread extends Thread {
private BufferedReader br = null;
private PrintStream os = null;
private final Socket clientSocket;
private final int clientId;
public ClientThread(int clientId, Socket clientSocket) {
this.clientSocket = clientSocket;
this.clientId = clientId;
}
public void run() {
try {
/*
* Create input and output streams for this client.
*/
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
os = new PrintStream(clientSocket.getOutputStream());
String line = "";
while ((line = br.readLine()) != null) {
System.out.printf("Client <%d> received message=<%s> via Client port: <%d>\n", clientId, line, clientSocket.getPort());
// Echo it back (as a test)
os.println(line);
}
br.close();
os.close();
clientSocket.close();
} catch (IOException e) {
}
System.out.println("Client has closed the session");
}
}
Let me know if you have any further questions at this time.

My chat server is responding to the correct thread/client but send button must be clicked equal to the number of clients

I have made a chat server using socket that can handle multiple clients and can reply to individual clients..the client can chat only with the server..But as the number client increases, the server has to click send button as same as the client's number.....i.e; one click to reply when there is only one client connected...click twice when there is two clients and so on..... how can i solve it???
The server is like:
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.PrintStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.ServerSocket;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Stream;
import javax.swing.SwingUtilities;
public class NewClass1{
private static ServerSocket serverSocket = null;
static Socket clientSocket = null;
private static final int maxClientsCount = 10;
private static final clientThread[] threads = new clientThread[maxClientsCount];
private static LinkedHashMap<String, clientThread> hm = new LinkedHashMap<String, clientThread>();
public static HashMap<String, clientThread> getinfo(){
return hm;
}
public static void main(String args[]) {
int portNumber = 22222;
if (args.length < 1) {
System.out.println("Usage: java MultiThreadChatServerSync <portNumber>\n"
+ "Now using port number=" + portNumber);
} else {
portNumber = Integer.valueOf(args[0]).intValue();
}
try {
serverSocket = new ServerSocket(portNumber);
} catch (IOException e) {
System.out.println(e);
}
while (true) {
try {
clientSocket = serverSocket.accept();
int i = 0;
for (i = 0; i < maxClientsCount; i++) {
if (threads[i] == null) {
(threads[i] = new clientThread(clientSocket, threads)).start();
System.out.println("hiiiiiiiiiii");
break;
}
}
if (i == maxClientsCount) {
PrintStream os = new PrintStream(clientSocket.getOutputStream());
os.println("Server too busy. Try later.");
os.close();
clientSocket.close();
}
} catch (IOException e) {
System.out.println(e);
}
}
}
}
class clientThread extends Thread {
static String clientName = null;
private BufferedReader br=null;
private DataInputStream is = null;
private PrintStream os = null;
private static Socket clientSocket = null;
private final clientThread[] threads;
private int maxClientsCount;
private static HashMap<String, clientThread> hm = new HashMap<>();
public clientThread(Socket clientSocket, clientThread[] threads) {
this.clientSocket = clientSocket;
this.threads = threads;
maxClientsCount = threads.length;
this.hm=NewClass1.getinfo();
}
public void run() {
final int maxClientsCount = this.maxClientsCount;
final clientThread[] threads = this.threads;
try {
br= new BufferedReader(new InputStreamReader(System.in));
is = new DataInputStream(clientSocket.getInputStream());
os = new PrintStream(clientSocket.getOutputStream());
os.flush();
String name;
while (true) {
os.println("Enter your name.");
name = is.readLine().trim();
if (name.indexOf('#') == -1) {
break;
} else {
os.println("The name should not contain '#' character.");
}
}
System.out.println("\n"+name+" has joined");
os.println("Welcome " + name
+ " to our chat room.\nTo leave enter /quit in a new line.");
synchronized (this) {
for (int i = 0; i < maxClientsCount; i++) {
if (threads[i] != null && threads[i] == this) {
clientName = "#"+name;
hm.put(clientName, this);
break;
}
}
for (int i = 0; i < maxClientsCount; i++) {
if (threads[i] != null && threads[i] != this) {
threads[i].os.println("*** A new user " + clientName
+ " entered the chat room !!! ***");
}
}
}
new Thread(new New()).start();
while(true){
String line=br.readLine();
if (line.startsWith("#")) {
String[] words = line.split("\\s", 2);
if (words.length > 1 && words[1] != null) {
words[1] = words[1].trim();
if (!words[1].isEmpty()) {
for(Map.Entry<String,clientThread> e:hm.entrySet()){
if(words[0].equals(e.getKey())){
clientThread get=e.getValue();
get.os.println("Server:\t" + words[1]);
os.flush();
System.out.println("\nServer to "+e.getKey()+":\t"+words[1]);
break;
}
else{
continue;
}
}
}}}
else { System.out.println("Please type #recipent's name.");
}}
} catch (IOException e) {
}
}
}
class New extends Thread{
public void run(){
DataInputStream is = null;
try {
is = new DataInputStream(NewClass1.clientSocket.getInputStream());
String lin=null;
while((lin=is.readLine())!=null)
{
//lin=is.readLine();
System.out.println(clientThread.clientName+": "+lin);
}
} catch (IOException ex) {
Logger.getLogger(New.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
is.close();
} catch (IOException ex) {
Logger.getLogger(New.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
The client is like:
import java.io.DataInputStream;
import java.io.PrintStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class NewClass implements Runnable {
// The client socket
private static Socket clientSocket = null;
// The output stream
private static PrintStream os = null;
// The input stream
private static DataInputStream is = null;
private static BufferedReader inputLine = null;
private static boolean closed = false;
public static void main(String[] args) {
// The default port.
int portNumber = 22222;
// The default host.
String host = "localhost";
if (args.length < 2) {
System.out
.println("Usage: java MultiThreadChatClient <host> <portNumber>\n"
+ "Now using host=" + host + ", portNumber=" + portNumber);
} else {
host = args[0];
portNumber = Integer.valueOf(args[1]).intValue();
}
/*
* Open a socket on a given host and port. Open input and output streams.
*/
try {
clientSocket = new Socket(host, portNumber);
inputLine = new BufferedReader(new InputStreamReader(System.in));
os = new PrintStream(clientSocket.getOutputStream());
is = new DataInputStream(clientSocket.getInputStream());
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + host);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to the host "
+ host);
}
/*
* If everything has been initialized then we want to write some data to the
* socket we have opened a connection to on the port portNumber.
*/
if (clientSocket != null && os != null && is != null) {
try {
/* Create a thread to read from the server. */
new Thread(new NewClass()).start();
while (!closed) {
String msg=inputLine.readLine();
os.println(msg.trim());
os.flush();
System.out.println("\nClient: \t"+msg);
}
/*
* Close the output stream, close the input stream, close the socket.
*/
os.close();
is.close();
clientSocket.close();
} catch (IOException e) {
System.err.println("IOException: " + e);
}
}
}
/*
* Create a thread to read from the server. (non-Javadoc)
*
* #see java.lang.Runnable#run()
*/
public void run() {
/*
* Keep on reading from the socket till we receive "Bye" from the
* server. Once we received that then we want to break.
*/
String responseLine;
try {
while ((responseLine = is.readLine()) != null) {
System.out.println("\n"+responseLine);
if (responseLine.indexOf("*** Bye") != -1)
break;
}
closed = true;
} catch (IOException e) {
System.err.println("IOException: " + e);
}
}
}

Multithreaded Disaster Client Server

I send information to the server, the server hangs for all eternity, any guidance is much appreciated. I think the problem is with one of the conidtional statements or the dataoutputstream but idk.
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public Client(Socket newSocket, int ID) {
// Set properties
id = ID;
socket = newSocket;
connected = true;
// Get input
inport = new Inport();
inport.start();
}
public static int conversion(int serverValue) {
if (serverValue >= 10) {
return 10;
} else
return serverValue;
}
/**
* Handles all incoming data from this user.
*/
private class Inport extends Thread {
private ObjectInputStream in;
//private DataInputStream in;
public void run() {
// Open the InputStream
try {
in = new ObjectInputStream(socket.getInputStream());
} catch (IOException e) {
System.out.println("Could not get input stream from " + toString());
return;
}
// Announce
System.out.println(socket + " has connected input.");
// Enter process loop
while (true) {
// Sleep
try {
} catch (Exception e) {
System.out.println(toString() + " has input interrupted.");
}
}
}
}
static String standOrHit = "";
private Socket socket;
private boolean connected;
private Inport inport;
static int serverValue;
static String serverName = "127.0.0.1"; //Our Server Name
static String selection = "";
static int port = 9999; //Our Server
static Scanner keyboard = new Scanner(System.in);
static boolean isTurn = true;
static boolean isGameOver = false;
static int score = 0;
static String sh = "It's your turn. Enter 'H' for Hit or 'S' for stand) \n Score:" + score;
static int id = 500;
public static void main(String[] args) throws IOException {
System.out.println("Fetching server connection...");
Socket client = new Socket(serverName, port); //Create a Client Socket and attempt to connect to the server # port
System.out.println("Connection Established.");
System.out.println("Fetching Player ID...");
System.out.println("Game Found you're Player " + 3 + ".");
System.out.println("Waiting for server...");
OutputStream outputStream = client.getOutputStream(); //Create a stream for sending data
DataOutputStream out = new DataOutputStream(outputStream); //Wrap that stream around a DataOutputStream
//InputStream is used for reading
InputStream inputStream = client.getInputStream(); //Read the incoming stream as bytes
DataInputStream dataInputStream = new DataInputStream(inputStream); //Read the inputStream and convert to primative times
// while (isGameOver == false) {
//Ask the User if what they want to do
System.out.println(sh);
selection = keyboard.nextLine();
//If they choose H
//if (selection.equals("H")) {
//Send the H to the Server(Works)
out.writeUTF(selection);
out.flush();
//Add server score to our score
// System.out.println(dataInputStream.readUTF());
while (dataInputStream.available() > 0) {
serverValue = dataInputStream.readInt();
}
score += conversion(serverValue);
System.out.println("Drew a " + serverValue + ".");
System.out.println("Waiting for player " + id);
//Loop back until
// }
//If they choose to stand just send S
if (selection.equals("S"))
{
//Send the H to the Server(Works)
out.writeUTF(selection);
out.flush();
}
// }
}
}
Server
import java.net.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Random;
/**
*
*/
public class Server extends Thread implements Runnable{
private ServerSocket serverSocket;
private Socket socket;
private ArrayList<Client> clients = new ArrayList<Client>();
private boolean isGameOver = false;
private Random rand;
private int scoreToAdd;
public Server(int port) throws IOException
{
serverSocket = new ServerSocket(port,2);
rand = new Random();
}
//Thread to execute once t.Start is called
public void run()
{
//Just as we are awaiting,print to the user.
System.out.println("Server started. Finding Clients...");
//System.out.println("Waiting for client on port : " + serverSocket.getLocalPort() + " ... ");
Socket server = null;
DataOutputStream dataOutputStream ;
//InputStream is used for reading
InputStream inputStream; //Read the incoming stream as bytes
DataInputStream dataInputStream; //Read the inputStream and convert to primative times
try {
//If the server is accepted, connect the user
//System.out.println("Connection Established.");
// Get a client trying to connect
server = serverSocket.accept();
//dataOutputStream = new DataOutputStream(server.getOutputStream());
//inputStream = server.getInputStream();
//dataInputStream = new DataInputStream(inputStream);
// Client has connected
System.out.println("Found Client "+ (clients.size()+1));
// Add user to list
clients.add(new Client(server,1));
}
catch (IOException e)
{
e.printStackTrace();
}
while (true)
{
try {
socket = serverSocket.accept();
dataOutputStream = new DataOutputStream(server.getOutputStream());
inputStream = server.getInputStream();
dataInputStream = new DataInputStream(inputStream);
// Client has connected
System.out.println("Found Client "+ (clients.size()+1));
System.out.println("Initiating Game...");
// Add user to list
clients.add(new Client(socket,1));
clients.get(0).isTurn = true;
while(isGameOver == false || ((clients.get(0).standOrHit.equals("S") && clients.get(1).standOrHit.equals("S")) == false))
{
if(clients.get(0).isTurn) {
System.out.println("Player 1's Turn");
if (dataInputStream.readUTF().equals("H")) {
//Generate a random number (Works)
System.out.println("Got H from Client");
//Send the random number in a outputbuffer (Works)
dataOutputStream.write(rand.nextInt(13) + 1);
dataOutputStream.flush();
clients.get(0).isTurn = false;
clients.get(1).isTurn = true;
}
}
else if (clients.get(1).isTurn)
{
System.out.println("Player 2's Turn");
if(dataInputStream.readUTF().equals("H"))
{
//Generate a random number (Works)
//System.out.println(rand.nextInt(13)+1);
//Send the random number in a outputbuffer (Works)
dataOutputStream.write(rand.nextInt(13)+1);
dataOutputStream.flush();
clients.get(1).isTurn = false;
clients.get(0).isTurn = true;
}
}
}
//Read input from the client
//DataInputStream dataInputStream = new DataInputStream(server.getInputStream());
//If we decide to hit
//if(dataInputStream.readUTF().equals("1"))
//{
//We want to send a random score 1-14
//rand = new Random();
// temp = rand.nextInt(14);
//}
//DataOutputStream dataOutputStream = new DataOutputStream(server.getOutputStream());
//dataOutputStream.writeUTF(Integer.toString(temp));
//dataOutputStream.flush();
// server.close();
}
catch (IOException e)
{
e.printStackTrace();
break;
}
}
}
public static void main(String [] args)
{
int port = 9999;
try
{
Thread t = new Server(port);
t.start();
}catch(IOException e)
{
e.printStackTrace();
}
}
}

Java TCP byteArray transfering using buffer and threading

So basically what I want to do is: Create a very simple multithreaded TCP server that can connect to several clients at once. This using threads and transferring messages through Byte[] and returning an echo of the message.
I have never touched anything related to server programming or TCP before, so I expect to have made a lot of mistakes. I am open for improvement and suggestions.
I made a simple Server class:
public class TCPEchoServer {
public static final int SERVERPORT = 4950;
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(SERVERPORT);
while (true) {
Socket clientSocket = serverSocket.accept();
Runnable connectionHandler = new TCPConnectionHandler(clientSocket);
new Thread(connectionHandler).start();
}
}
}
And the connection handler class:
public class TCPConnectionHandler implements Runnable {
private final Socket clientSocket;
private int msgLength = 0;
private byte[] data;
public TCPConnectionHandler(Socket clientSocket) {
this.clientSocket = clientSocket;
}
#Override
public void run() {
try {
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(clientSocket.getOutputStream());
InputStream in = clientSocket.getInputStream();
DataInputStream dis = new DataInputStream(in);
msgLength = dis.readInt();
data = new byte[msgLength];
if (msgLength > 0) {
dis.readFully(data);
}
String message = inFromClient.readLine();
System.out.println("Message recieved: " + message);
outToClient.writeBytes(String.valueOf(data));
clientSocket.close();
}
catch (IOException e) {
System.out.printf("Could not listen on port: " + clientSocket.getLocalPort());
}
}
}
And the Client class:
public class TCPEchoClient {
public static final int MYPORT = 0;
public static int BUFFSIZE = 0;
public static Socket socket;
public static final String MSG = "An Echo Message! LOL";
public static String RETURNMSG = "";
public static final byte[] messageByteArr = MSG.getBytes(Charset.forName("UTF-8"));
private static final Pattern PATTERN = Pattern.compile(
"^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
public static void main(String[] args) throws IOException, InterruptedException {
if (args.length != 4) {
System.err.printf("ERROR: The EchoClient expects 4 parameter inputs:");
System.out.printf("IP address, Port number, message rate (msg/second).");
System.exit(1);
}
if (!isValidIP(args[0])) {
System.out.printf("ERROR: The entered IP address is not a valid IPv4 address.");
System.out.printf("Please enter a valid IPv4 address as the first argument.");
System.exit(1);
}
if (Integer.parseInt(args[1]) < 0 || Integer.parseInt(args[1]) > 65535) { //If the portnumber is negative or bigger than the highest portnumber (unsigned 16-bit integer)
System.out.printf("ERROR: The chosen portnumber is outside the available range.");
System.out.printf("Expected portnumbers: 0-65535");
System.exit(1);
}
if (Integer.parseInt(args[3]) < messageByteArr.length) {
System.out.println("Buffer size can not be smaller than the message size.");
System.out.println("Current message size: " + messageByteArr.length);
System.exit(1);
}
BUFFSIZE = Integer.parseInt(args[3]);
byte[] buf = new byte[BUFFSIZE];
DataOutputStream outToServer = null;
BufferedReader serverEcho = null;
try {
socket = new Socket(args[0], Integer.parseInt(args[1]));
outToServer = new DataOutputStream(socket.getOutputStream());
serverEcho = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (UnknownHostException e) {
System.out.println("Unknown host address: " + args[0]);
System.exit(1);
} catch (IOException e) {
System.out.println("Could not access port " + Integer.parseInt(args[1]));
System.exit(1);
}
int msgLength = 0;
int msgStart = 0;
if (msgLength < 0) {
throw new IllegalArgumentException("Negative length not allowed.");
}
if (msgStart < 0 || msgStart >= messageByteArr.length) {
throw new IndexOutOfBoundsException("Out of bounds: " + msgStart);
}
for (int i = 1; i <= Integer.parseInt(args[2]); i++) {
outToServer.writeInt(msgLength);
if (msgLength > 0) {
outToServer.write(messageByteArr, msgStart, msgLength);
System.out.println("Message sent: " + MSG);
}
RETURNMSG = serverEcho.readLine();
System.out.println("ECHO MESSAGE: " + RETURNMSG);
}
socket.close();
}
private static boolean isValidIP(final String ip) {
return PATTERN.matcher(ip).matches();
}
}
I ran into a problem just now as well, the print outs worked before on the client and sever, but now when a message is sent. Nothing happens at all.
My main question is how I can incorporate a buffer and use it when sending and receiving messages.
You have a loop in the client that will wait args[2] times the RETURNMSG, the server will send this message only once. The RETURNMSG reading code should be outside (after) the for loop.
You should flush the buffer once you've finished writing in it.
This should be done in both client and server, since your client will wait the RETURNMSG forever depending how your protocol will evolve in the future.

Server socket always return null to the client , Java

I, doing some computer network homework and I have to develop some sort of distributed DBMS which are connected to each other with peer to peer network, so I have a TCP client and a TCP server in one .java file which running next to each other by threads. the TCP Server of the class always listen to the other TCP client from others and give them service, the problem is when I System.out the String which I have to send back to the client on the Server side it's in the way which it's supposed to be but after sending , the client gets nothing and prints null. I wrote my code based on tutorials I found on the net and I when I test them they worked well but it's not working in my own code. could you see where my problem is? thanks
class CommandComp
{
int PORT = 1210;
int PORT2 = 1211;
String IPLocal = "";
String IPdest = "";
InetAddress IPAD;
InetAddress IPAD2;
int numOfNodes;
int numOfNodesnonchanged;
String[] Nodes;
Random rand = new Random();
int max = 2000;
int min = 1000;
String command;
Socket clientSocket;
CommandComp(String[] IPdest, String IPLocal, int numOfNodes, String command)
{
try
{
this.numOfNodes = numOfNodes;
numOfNodesnonchanged = numOfNodes;
this.IPLocal = IPLocal;
this.Nodes = IPdest;
this.command = command;
// this.IPAD = InetAddress.getByName(this.IPdest);
this.IPAD2 = InetAddress.getByName(this.IPLocal);
// clientSocket = new Socket(this.IPAD , PORT ,this.IPAD2 , PORT2 );
}
catch (Exception e)
{
// //e.printStackTrace();
}
}
public String call()
{
int i = 0;
while (numOfNodes > 0)
{
String response = "";
try
{
Thread.sleep(rand.nextInt(max - min + 1) + min);
i = numOfNodes - 1;
int max2 = 50;
int min2 = 10;
this.IPAD = InetAddress.getByName(Nodes[i]);
clientSocket = new Socket(this.IPAD, PORT, this.IPAD2, PORT2 + rand.nextInt(max2 - min2 + 1) + min2);
PrintWriter outToServer = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
outToServer.println(command);
System.out.println(inFromServer.readLine());
response = inFromServer.readLine();
outToServer.close();
inFromServer.close();
clientSocket.close();
numOfNodes--;
System.out.println(Nodes[i] + " Remote DBMS");
System.out.println(response);
}
catch (Exception e)
{
e.printStackTrace();
try
{
clientSocket.close();
}
catch (Exception e2)
{
// TODO: handle exception
}
}
}
return command;
}
}
class TCPListnerService
implements Callable<Object>
{
String from;
String to;
ServerSocket Server;
String IP = "";
int numOfNodes;
int numofNodesUnchanged;
static clientThread t[];
TCPListnerService(String IP, int numOfNodes)
{
try
{
this.IP = IP;
this.numOfNodes = numOfNodes;
numofNodesUnchanged = numOfNodes * 2;
this.t = new clientThread[numofNodesUnchanged];
InetAddress IPAD = InetAddress.getByName(IP);
Server = new ServerSocket(1210, 20, IPAD);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public String call()
throws Exception
{
String gotten = "";
while (numOfNodes > 0)
{
Socket connected = Server.accept();
for (int i = 0; i < numofNodesUnchanged; i++)
{
if (t[i] == null)
{
(t[i] = new clientThread(connected)).start();
break;
}
}
}
return gotten;
}
}
class clientThread
extends Thread
{
Socket clientSocket = null;
sqlite DB = new sqlite();
String response = "";
String fromclient;
String delims = "[ =)(',\n\t\r]+";
String[] tokens;
public clientThread(Socket clientSocket)
{
this.clientSocket = clientSocket;
}
public void run()
{
try
{
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter outToClient = new PrintWriter(clientSocket.getOutputStream(), true);
fromclient = inFromClient.readLine();
tokens = fromclient.split(delims);
if (tokens[0].equalsIgnoreCase("create")
|| tokens[0].equalsIgnoreCase("drop")
|| tokens[0].equalsIgnoreCase("delete")
|| tokens[0].equalsIgnoreCase("insert")
|| tokens[0].equalsIgnoreCase("update")
|| tokens[0].equalsIgnoreCase("select"))
{
response = DB.RunQuery(fromclient);
System.out.println(response);
outToClient.print(response);
clientS.close();
}
else if (tokens[0].equalsIgnoreCase("shut"))
{
System.exit(0);
}
inFromClient.close();
outToClient.close();
clientSocket.close();
}
catch (Exception e)
{
}
;
}
}
The problem is here:
inFromClient.close();
outToClient.close();
clientSocket.close();
You are closing (1) the input stream, which closes the socket, (2) the PrintWriter, which flushes it and closes the socket, and (3) the socket. Obviously (2) cannot succeed if the socket is already closed. The data you sent to the client is still buffered, never got flushed, so it never got sent.
Just close the PrintWriter, and close the socket in a finally block in case (2) fails somehow. No need to close the input at all.

Categories

Resources