I have written this simple java server which is ready to accept connections on a port using server sockets.
I want that whenever some client tries to send some data on this port within same local network I want to:
1.print that data ie: read from inputstream using InputStreamReader into a buffer and then print into console.
2.send some data back to the client by writing on outputstream using OutPutStreamWriter.
3.close both the streams ie: outputStreamWriter and inputStreamReader and then finally close the socket.
The problem which I am facing is that I am able to do only one at a time even though I have created two separate threads for both input and output.
Example if I fire a request on port 8086 from any device within the same network everything gets blocked (mabye a deadlock) nothing is printed onto the console unless the client who made the request itself cancels the request.
similarly if I terminate the connection from server ie: terminate the java application then on the client side I get this response string "success".
I don't know why the streams are not getting closed after the process even though I have closed them.
I thought if we write onto outputstream and read in from inputstream in two different threads it would solve the problem but still no luck.
Can anybody help?
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class Notification {
private Socket clientSocket;
private BufferedReader buffInputStream;
private InputStreamReader inputStreamReader;
private OutputStreamWriter outputStreamWriter;
private OutputStream outputstream;
private InputStream inputstream;
public Notification(){
}
public void start() {
Thread listenThread = new Thread(listen);
listenThread.start();
}
Runnable listen = new Runnable() {
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(8086);
while(true){
clientSocket = serverSocket.accept();
Thread t2 = new Thread(inStream);
t2.start();
Thread t1 = new Thread(outStream);
t1.start();
t1.join();
t2.join();
buffInputStream.close();
inputStreamReader.close();
outputStreamWriter.close();
clientSocket.close();
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable outStream = new Runnable() {
#Override
public void run() {
try {
outputstream = clientSocket.getOutputStream();
outputStreamWriter = new OutputStreamWriter(outputstream);
outputStreamWriter.write("success");
outputStreamWriter.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
};
Runnable inStream = new Runnable() {
#Override
public void run() {
try {
inputstream = clientSocket.getInputStream();
inputStreamReader = new InputStreamReader(inputstream);
buffInputStream = new BufferedReader(inputStreamReader);
List<String> response = new ArrayList<>();
String line;
while ((line = buffInputStream.readLine()) != null) {
response.add(line);
}
String arr[] = response.toArray(new String[response.size()]);
for (String re : arr) {
System.out.println(re);
}
}
catch (IOException e){
e.printStackTrace();
}
}
};
}
There is no deadlock here. Your read thread simply isn't printing anything until the peer disconnects. Print each line as you read it, not after end-of-stream is received. You don't have any need for the list, or the array, or the second loop.
But this will never work. You're sharing a single clientSocket reference among all clients. You need to create Runnables that take the client socket as a parameter and store it as an instance variable.
Related
I have created this code snippet in both a single threaded version and multithreaded for a client/server setup I have going. I have tested both (recording the avg turn around time) and have gotten EXTREMELY similar results within margin of error when running multiple simple server commands at once. have I implememnted my client handler wrong?
This is my first time trying to implement a multithreaded server and from my understanding it just a matter of putting in a client handler being
`
class ServerThread extends Thread {
private Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
`
below is the snippet of the whole server code.
`
public class Server {
public static void main(String[] args) {
if (args.length < 1) return;
int port = Integer.parseInt(args[0]);
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("Server is listening on port " + port);
while (true) {
Socket socket = serverSocket.accept();
System.out.println("New client connected");
new ServerThread(socket).start();
}
} catch (IOException ex) {
System.out.println("Server exception: " + ex.getMessage());
ex.printStackTrace();
}
}
}
class ServerThread extends Thread {
private Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
public void run() {
try {
InputStream input = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
OutputStream output = socket.getOutputStream();
PrintWriter writer = new PrintWriter(output, true);
String text;
do {
text = reader.readLine(); // reads text from client
Process p = Runtime.getRuntime().exec(text);
BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
String outputLine;
while ((outputLine = stdout.readLine()) != null) { // while serverMsg is not empty keep printing
writer.println(outputLine);
}
stdout.close();
writer.println("ENDCMD");
// Text here should just write back directly what the server is reading...?
}
while (!text.toLowerCase().equals("exit"));
socket.close();
} catch (IOException ex) {
System.out.println("Server exception: " + ex.getMessage());
ex.printStackTrace();
}
}
}
`
I have tested both (recording the avg turn around time) and have gotten EXTREMELY similar results within margin of error when running multiple simple server commands at once. have I implememnted my client handler wrong?
If you are not making a new connection for each command that you send, then this would be expected. Since each connection runs on one thread, a multi-threaded approach, as you have shown, would have the same speed as if you didn't make a new thread for each connection. The difference is that, without multi-threading, you can only have one connection at a time.
I started working with sockets this week and I'm having a hard time.
My goal is when the client sent a message the server responded with a notification.
On the client side sending to the server has no problem, but when the server sends to the client nothing appears.
Can anybody help me with this problem?
Client:
Thread thread = new Thread(new myServerThread());
thread.start();
class myServerThread implements Runnable {
Socket socket;
ServerSocket serverSocket;
InputStreamReader inputStreamReader;
BufferedReader bufferedReader;
String message;
Handler handler = new Handler();
#Override
public void run() {
try {
serverSocket = new ServerSocket(5000);
while (true){
socket = serverSocket.accept();
inputStreamReader = new InputStreamReader(socket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader);
message = bufferedReader.readLine();
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), message,Toast.LENGTH_LONG).show();
}
});
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
SERVER:
String EMAIL = "Email";
try {
serverSocket = new ServerSocket(6000);
while(true){
socket = serverSocket.accept();
inputStreamReader = new InputStreamReader(socket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader);
email = bufferedReader.readLine();
System.out.println(email);
if(email.equals(EMAIL)){
jTextArea1.setText(email);
try {
socket = new Socket("localHost", 5000);
PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
printWriter.write(message);
printWriter.flush();
printWriter.close();
System.out.println("connected");
} catch (IOException e) {
e.printStackTrace();
}
}else{
}
}
} catch (IOException ex) {
}
etEmail = findViewById(R.id.etvEmail);
First the short answer: Your Java codes are both working almost fine.
Anyway, you should always test your application against another program that is known to be OK. By testing one self-written program against another fresh self-written program, it is difficult to say which of both is broken. It seems that you are testing it with some GUI (Android?). Transforming the relevant part to a simple console application which you run on a regular PC makes troubleshooting much easier.
So let me show how I checked your code on my Linux laptop:
First copy your "client" code into a "Hello-World" template. I added some debug messages and a loop which allows the client to receive more than one single line of text:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
class Main
{
static class myServerThread implements Runnable
{
Socket socket;
ServerSocket serverSocket;
InputStreamReader inputStreamReader;
BufferedReader bufferedReader;
String message;
#Override
public void run()
{
try
{
serverSocket = new ServerSocket(5000);
while (true)
{
System.out.println("Accepting...");
socket = serverSocket.accept();
System.out.println("Connected...");
inputStreamReader = new InputStreamReader(socket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader);
String message = bufferedReader.readLine();
while (message!=null)
{
System.out.println("Received:" + message);
message = bufferedReader.readLine();
}
System.out.println("Closing...");
socket.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
public static void main(String[] args)
{
Thread thread = new Thread(new myServerThread());
thread.start();
}
}
I started the "client" and opened another command window to open a network connection with Netcat and send two lines of text:
nc localhost 5000
Hallo
Test
The related output of the "client" program was:
Accepting...
Connected...
Received:Hallo
Received:Test
Closing...
Accepting...
So the "client" part is running fine obviously.
Next I copied your "server" code into a "Hello World" template:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
class Main
{
static class myServerThread implements Runnable
{
Socket socket;
ServerSocket serverSocket;
InputStreamReader inputStreamReader;
BufferedReader bufferedReader;
String message;
#Override
public void run()
{
String EMAIL = "Email";
try
{
serverSocket = new ServerSocket(6000);
while (true)
{
System.out.println("Accepting...");
socket = serverSocket.accept();
System.out.println("Connected...");
inputStreamReader = new InputStreamReader(socket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader);
String message = bufferedReader.readLine();
while (message != null)
{
System.out.println("Received:" + message);
if (message.equals(EMAIL))
{
System.out.println("Sending...");
try
{
socket = new Socket("localHost", 5000);
PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
printWriter.write(message);
printWriter.flush();
printWriter.close();
System.out.println("sending done");
}
catch (IOException e)
{
e.printStackTrace();
}
}
message = bufferedReader.readLine();
}
System.out.println("Closing...");
socket.close();
}
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}
public static void main(String[] args)
{
Thread thread = new Thread(new myServerThread());
thread.start();
}
}
Again I added some debug messages and a loop, so the server can receive multiple lines of text. Since this Java program handles two connections, I had to open two command windows.
In the first command window I tell NetCat to accept (listen) connection on port 5000. That is where your "server" will send the "Email" message to:
nc -lp 5000
In the second command window I tell Netcat to connect to your "server" on port 6000, then I send two lines of text and then I press Ctrl-C to stop it:
nc localhost 6000
Test
Email
^C
The related output of the "server" program is:
Accepting...
Connected...
Received:Test
Received:Email
Sending...
sending done
Closing...
Accepting...
And my listening Netcat in the other (first) command windows produced this output:
stefan#stefanpc:/hdd/stefan$ nc -lp 5000
Emailstefan#stefanpc:/hdd/stefan$
So everything looks fine on my machine. Beside one small detail: There is no line break after the "Email" that your "server" sends to the client (in this case NetCat). So the fix is simple:
printWriter.write(message+"\n");
This final line break is required because your client consumes the input by readLine().
NetCat is a very helpful tool to test plain text TCP socket communication. It is included in all Linux distributions. If you have difficulties to find a Windows executable, then take it from my homepage: http://stefanfrings.de/avr_tools/netcat-win32-1.12.zip
Please comment if that was helpful to you.
basically what i want to do is develop a chat program(something between an instant messenger and IRC) to improve my java skills.
But I ran into 1 big problem so far: I have no idea how to set up streams properly if there is more than one client. 1:1 chat between the client and the server works easily, but I just don't know what todo so more than 1 client can be with the server in the same chat.
This is what I got, but I doubt its going to be very helpful, since it is just 1 permanent stream to and from the server.
private void connect() throws IOException {
showMessage("Trying to connect \n");
connection = new Socket(InetAddress.getByName(serverIP),27499);
showMessage("connected to "+connection.getInetAddress().getHostName());
}
private void streams() throws IOException{
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
showMessage("\n streams working");
}
To read from multiple streams in one program, you're going to have to use multithreading. Because reading from streams is synchronous, you'll need to read from one stream for each thread. See the java tutorial on threads for more info on multithreading.
I've done this several times with ServerSocket(int port) and Socket ServerSocket.accept(). This can be pretty simple by having it listen to the one port you want your chat server client listening on. The main thread will block waiting for the next client to connect, then return the Socket object to that specific client. Usually you'll want to put them in a list to generically handle n-number of clients.
And, yes, you will probably want to make sure each Socket is in a different thread, but that's entirely up to you as the programmer.
Remember, there is no need to re-direct to another port on the server, by virtue of the client using a different source port, the unique 5-tuple (SrcIP, SrcPort, DstIP, DstPort, TCP/UDP/other IP protocol) will allow the one server port to be re-used. Hence why we all use stackoverflow.com port 80.
Happy Coding.
Made something like that a few months back. basically I used a separate ServerSocket and Thread per client server side. When client connects you register that port's input and output streams to a fixed pool and block until input is sent. then you copy the input to each of the other clients and send. here is a basic program run from command line:
Server code:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class ChatServer {
static int PORT_NUMBER = 2012;
public static void main(String[] args) throws IOException {
while (true) {
try (ServerSocket ss = new ServerSocket(PORT_NUMBER)) {
System.out.println("Server waiting #" + ss.getInetAddress());
Socket s = ss.accept();
System.out.println("connection from:" + s.getInetAddress());
new Worker(s).start();
}
}
}
static class Worker extends Thread {
final static ArrayList<PrintStream> os = new ArrayList(10);
Socket clientSocket;
BufferedReader fromClient;
public Worker(Socket clientSocket) throws IOException {
this.clientSocket = clientSocket;
PrintStream toClient=new PrintStream(new BufferedOutputStream(this.clientSocket.getOutputStream()));
toClient.println("connected to server");
os.add(toClient);
fromClient = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
}
#Override
public void run() {
while (true) {
try {
String message = fromClient.readLine();
synchronized (os) {
for (PrintStream toClient : os) {
toClient.println(message);
toClient.flush();
}
}
} catch (IOException ex) {
//user discnnected
try {
clientSocket.close();
} catch (IOException ex1) {
}
}
}
}
}
}
Client code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException {
final BufferedReader fromUser = new BufferedReader(new InputStreamReader(System.in));
PrintStream toUser = System.out;
BufferedReader fromServer;
final PrintStream toServer;
Socket s = null;
System.out.println("Server IP Address?");
String host;
String port = "";
host = fromUser.readLine();
System.out.println("Server Port Number?");
port = fromUser.readLine();
s = new Socket(host, Integer.valueOf(port));
int read;
char[] buffer = new char[1024];
fromServer = new BufferedReader(new InputStreamReader(s.getInputStream()));
toServer = new PrintStream(s.getOutputStream());
new Thread() {
#Override
public void run() {
while (true) {
try {
toServer.println(">>>" + fromUser.readLine());
toServer.flush();
} catch (IOException ex) {
System.err.println(ex);
}
}
}
}.start();
while (true) {
while ((read = fromServer.read(buffer)) != -1) {
toUser.print(String.valueOf(buffer, 0, read));
}
toUser.flush();
}
}
}
I'm having some trouble simulating a connection to my Server Socket, accept seems to continue blocking as it doesn't "see" the connection.
Here's some simplified code
#Test
public void testPDMServerThread() {
try {
ServerSocket serverSocket = new ServerSocket(0);
int port = serverSocket.getPort();
Socket clientSocket = new Socket("localhost", port);
PrintWriter clientRequest = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader serverResponse = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
serverThread = new ProducerMonitorServerThread(serverSocket.accept());
clientRequest.write("Hi!");
serverThread.start();
System.out.println("Server says: " + serverResponse.readLine());
assertEquals("RUNNABLE", serverThread.getState().toString());
} catch (IOException e) {
}
}
And here's the thread where the server should respond
public class ProducerMonitorServerThread extends Thread {
private Socket socket;
public ProducerMonitorServerThread(Socket socket) {
super("PDM");
this.socket = socket;
}
#Override
public void run() {
try {
PrintWriter serverResponse = new PrintWriter(socket.getOutputStream(), true);
BufferedReader clientRequest = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String serverInput, clientOutput;
while((serverInput = clientRequest.readLine()) != null) {
clientOutput = "Bye!";
System.out.println("Client says: " +serverInput);
serverResponse.write(clientOutput);
}
serverResponse.close();
clientRequest.close();
socket.close();
} catch (IOException e) {
}
}
}
It never seems to get past this line which is why I think accept is not seeing the connection
serverThread = new ProducerMonitorServerThread(testServer.accept());
I'm sure there's something fundamental that I'm just not seeing.
First of all, you should not ignore exceptions like you're doing.
The problem is not with accept. The problem is that the server uses readLine(), and the client never sends any EOL character, and never closes the socket. So the server is blocked waiting for an EOL to appear in the reader. The same is true for the client: it uses readLine() and the server never sends any EOL.
Use a debugger. It will help you find the cause of such problems.
I'm trying to get a simple multithreaded proxy to work in Java. However I don't manage to get the webpage show up in my browser, after the first GET request and the response from the webpage, the program is just stuck (as you can see from my code, I'm printing everything i get on the stdout for debugging, and there I see the sourcecode of the webpage, however after printing out "After Client Write", nothing happens (no exception, just nothing...)).
import java.net.*;
import java.util.*;
import java.io.*;
public class Proxy
{
public static void main(String[] args)
{
try
{
ServerSocket listensocket = new ServerSocket(Integer.valueOf(args[0]));
while(true)
{
System.out.println("wait");
Socket acceptsocket = listensocket.accept(); // blocking call until it receives a connection
myThread thr = new myThread(acceptsocket);
thr.start();
}
}
catch(IOException e)
{
System.err.println(">>>>" + e.getMessage() );
e.printStackTrace();
}
}
static class myThread extends Thread
{
Socket acceptsocket;
int host, port;
String url;
myThread(Socket acceptsocket)
{
this.acceptsocket=acceptsocket;
}
public void run() {
try
{
System.out.println("hello");
Socket client = acceptsocket;
//client.setSoTimeout(100);
InputStream clientIn = client.getInputStream();
//BufferedInputStream clientIn=new BufferedInputStream(clientis);
OutputStream clientOut = client.getOutputStream();
System.out.println("hello");
String clientRequest = readStuffFromClient(clientIn); // parses the host and what else you need
System.out.print("Client request: -----\n"+clientRequest);
Socket server;
server = new Socket("xxxxxxxxxxxxx" , 80);
InputStream serverIn = server.getInputStream();
//BufferedInputStream serverIn=new BufferedInputStream(serveris);
OutputStream serverOut = server.getOutputStream();
serverOut.write(clientRequest.getBytes());
serverOut.flush();
String serverResponse = readStuffFromClient(serverIn);
System.out.print("Server Response: -----\n"+serverResponse);
clientOut.write(serverResponse.getBytes());
clientOut.flush();
System.out.println("After Client Write");
clientIn.close();
clientOut.close();
serverIn.close();
serverOut.close();
server.close();
client.close();
}
catch(Exception e)
{
System.out.println(e);
}
}
private String readStuffFromClient(InputStream clientdata)
{
ByteArrayOutputStream response = new ByteArrayOutputStream();
StringBuffer request=new StringBuffer(8192);
int i, httpstart,n=-1 ;
byte[] buffer = new byte[8192];
System.out.println("beforetry");
try
{
while((n = clientdata.read(buffer))!=-1)
{
System.out.println("before");
response.write(buffer,0,n);
//response.flush();
}
request=new StringBuffer(response.toString());
/*System.out.println("new:"+n+" "+ request.toString());
System.out.println("End client data");*/
}
catch (Exception e)
{
System.out.println("here");
System.out.println(e);
e.printStackTrace();
i = -1;
}
System.out.println("End manipulation method");
return request.toString();
}
}
}
(this is a stripped down not working example of my program, from the comments one can see I already tried to use BufferedInputStream). In general, this program is very unresponsive even for the first GET request from the browser. When I only read the clientdata once (not in a loop), I get a little bit further, e.g. get more GET/Response pairs, but at some point the program still gets stuck.
Somehow I think either I've a real trivial error I just don't manage to see, or the program should work, but simply doesn't for no real reason.
Any help is appreciated, thanks in advance!
You need two threads: one to read from the client and write to the server, and one to do the opposite, for each accepted socket. There is a further subtlety: when you read EOS from one direction, shutdown the opposite socket for output, and then if the input socket for that thread is already shutdown for output, close both sockets. In both cases exit the thread that read the EOS.
Try getting first the OutputStream and then the InputStream!
InputStream clientIn = client.getInputStream();
OutputStream clientOut = client.getOutputStream();
change it to:
OutputStream clientOut = client.getOutputStream();
InputStream clientIn = client.getInputStream();
This will make it work:
It will check if there is more data available to read
Still, it's important that you use BufferedIS because I think ByteArrayIS doesn't implement available method.
BufferedInputStream bis = new BufferedInputStream(clientdata);
System.out.println("beforetry");
try {
while(bis.available() > 0){
n = bis.read(buffer);
response.write(buffer, 0, n);
}