I'm trying to code a server-client communicating application which uses two separate threads, one for input and one for output. I'm having a weird "deadlock" issue, though: when one thread reads input, but the client hasn't sent anything, the thread stops (since it's waiting for input). However, for some reason, while the input thread is blocked, the output thread can't write anything.
This is illustrated in this code sample:
import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
public class TestServer {
public static void main(String... args) throws IOException {
/* Creates a server socket that lurks about our port waiting for connections */
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
serverChannel.socket().bind(new InetSocketAddress(4114));
while(true){
SocketChannel connectionChannel = serverChannel.accept();
if(connectionChannel != null){
final Socket connection = connectionChannel.socket();
new Thread(){
public void run(){
try {
System.out.println("READING");
System.out.flush();
// If the next line is commented out, nothing blocks
connection.getInputStream().read();
System.out.println("DONE READING");
System.out.flush();
} catch (Exception e){
e.printStackTrace();
}
}
}.start();
new Thread(){
public void run(){
try {
System.out.println("WRITING");
System.out.flush();
new DataOutputStream(connection.getOutputStream()).writeBytes("AUGH!!!");
//connection.getOutputStream().write(5);
System.out.println("DONE WRITING");
System.out.flush();
} catch (Exception e){
e.printStackTrace();
}
}
}.start();
break;
}
}
}
}
And the client code:
import java.net.*;
import java.io.*;
public class TestClient {
public static void main(String... args) throws IOException {
Socket connection = new Socket("127.0.0.1", 4114);
while(true){
System.out.println(connection.getInputStream().read());
}
}
}
The code sample above blocks, but if the line in the server is commented out it doesn't. Why is that? Is a socket limited to only waiting for input/output at the same time? What's going on?
I'm not sure why you are seeing this, but it has something to do with using channels.
If you replace this code with
ServerSocket ss = new ServerSocket(4114);
Socket connection = ss.accept();
it will work as you want.
Related
I had stumbled upon a dead block when doing my assignment. It's a simple server and client program.
The details of this program is as follows;
Create a server class EncryptServer that listens for incoming connections. If there is a connection, accept it and create a thread EncryptServerSession to handle the input and output stream.
Create a thread class EncryptServerSession that takes in the input and output stream from the server class and process it.
Create a client class EncryptClient that connects to the server class and takes output stream from EncryptServerSession through EncryptServer.
Somehow the while true loop of the EncryptClient class is not working. I cannot seem to get into the loop. Is something wrong with my code? Thanks in advance.
EncryptServer
import java.net.*;
import java.io.*;
public class EncryptServer
{
public EncryptServer() throws IOException
{
ServerSocket serverSocket = new ServerSocket(1122);
System.out.println("Server started.");
while (true)
{
Socket conSocket = serverSocket.accept();
System.out.println("Client connected from " +
conSocket.getLocalAddress().getHostName());
Thread session = new
EncryptServerSession(conSocket.getInputStream(),
conSocket.getOutputStream());
session.start();
}
}
public static void main(String[] args)
{
try
{
EncryptServer server = new EncryptServer();
}
catch (Exception e)
{
System.out.println(e);
}
}
}
EncryptServerSession
import java.net.*;
import java.io.*;
public class EncryptServerSession extends Thread
{
BufferedReader in;
Writer out;
public EncryptServerSession(InputStream inStream, OutputStream outStream)
{
Reader read = new InputStreamReader(inStream);
in = new BufferedReader(read);
out = new OutputStreamWriter(outStream);
}
public void strEncrypt()
{
try
{
String message = in.readLine();
out.write(message);
out.flush();
}
catch (Exception e)
{
}
}
public void run()
{
try
{
//System.out.println(in.readLine());
out.write("Please enter the message to be encrypted: ");
out.flush();
//strEncrypt();
}
catch (Exception e)
{
System.out.println(e);
}
}
}
EncryptClient
import java.net.*;
import java.io.*;
public class EncryptClient
{
BufferedReader input, userTerm;
Writer output;
String line;
public EncryptClient() throws IOException
{
Socket clientSocket = new Socket("localhost", 1122);
Reader read = new InputStreamReader(clientSocket.getInputStream());
input = new BufferedReader(read);
userTerm = new BufferedReader(new InputStreamReader(System.in));
output = new OutputStreamWriter(clientSocket.getOutputStream());
/////////////// Somehow I cannot get into this loop, why? //////////
while (true)
{
System.out.println("test ");
System.out.println(input.readLine());
System.out.println("Enter message to be encrypted: ");
output.write(userTerm.readLine());
output.flush();
}
/////////////// Somehow I cannot get into this loop, why? //////////
}
public static void main(String[] args)
{
try
{
EncryptClient client = new EncryptClient();
}
catch (Exception e)
{
System.out.println(e);
}
}
}
As I understand, you are trying to send a message to a server, do some logic, then send it back to the client. The above code seems to run well on my side. Here's what I've done:
run EncryptServer first. I expect this is the issue you are facing. or maybe your firewall isn't letting you listen on sockets.
in EncryptServerSession, You are reading lines but you aren't writing lines. either close the stream or write a new line after you finish.
...
out.write(message);
out.write("\r\n"); // write new line
out.flush();
...
} finally {
try {
out.close();
} catch (IOException e) {
}
}
OR
...
out.write(message);
out.write("\r\n"); // write new line
out.flush();
...
If I have a server and a client and I opened a socket between the two:
1.Is it possible that the client will have a printWriter stream, in order to write things to the socket, but the server won't have in the mean time a bufferReader?
If the answer of 1 is yes, if that client will send a message to the server (who currently doesn't have a reading stream), what will happend to this message until te server will create a reading stream and read the message?
thank you
This is not at all specific to Java, but TCP/IP. There are buffers to keep the data received, so it's not possible that some data would be lost because one end isn't "ready" yet. This is because TCP will retransmit data that hasn't been acknowledged as received, guaranteeing that all the bytes that are written are received on the other (barring obvious cases).
in addition to #Kayaman's answer:
consider this Compile-able simple Java implemented example:
Server Side:
import java.io.*;
import java.net.*;
public class SimpleServer implements Runnable{
int serverPort = 45000;
ServerSocket serverSocket = null;
boolean isStopped = false;
public SimpleServer(int port){
this.serverPort = port;
}
public void run(){
try {
serverSocket = new ServerSocket(serverPort);
} catch (IOException e) {
System.err.println("Cannot listen on this port.\n" + e.getMessage());
System.exit(1);
}
while(!isStopped){
try {
Socket clientSocket = serverSocket.accept();
} catch (IOException e) {
// do nothing
}
}
}
public static void main(String[] args) throws IOException {
SimpleServer server = new SimpleServer(45000);
new Thread(server).start();
System.out.println("Server is waiting to connect");
}
}
Client Side:
import java.io.*;
import java.net.*;
public class SimpleClient {
public static void main(String[] args) throws IOException {
Socket socket = null;
PrintWriter out = null;
try {
socket = new Socket("127.0.0.1", 45000);
out = new PrintWriter(socket.getOutputStream(), true);
System.out.println("output stream created");
out.write(9);
System.out.println("message was sent to output with no listener");
} catch (UnknownHostException e) {
// do nothing
} catch (IOException e) {
// do nothing
}
}
}
the example is an implementation of a very basic client server connection in which a socket is created and a stream is defined only on the client side, followed by a write to the stream that will eventually be read by the server (if at all).
therefore, to answer you questions:
1) yes, it's possible to open a one-way connection stream without a "listener"
2) edit: according to #EJP: It will be saved within the socket's buffer until it is read or the socket is closed.
I am trying to reproduce "java.net.SocketException.Connection reset" exception.
Wanted to know if there is any program available which could help me simulate it. I tried following Server and client programs to see if I could simulate but I am not able to get any exception. I am using java8.
Server Code-
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
public class SimpleServerApp {
public static void main(String[] args) throws InterruptedException {
new Thread(new SimpleServer()).start();
}
static class SimpleServer implements Runnable {
#Override
public void run() {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(3333);
serverSocket.setSoTimeout(0);
//serverSocket.
while (true) {
try {
Socket clientSocket = serverSocket.accept();
BufferedReader inputReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
System.out.println("Client said :"+ inputReader.readLine());
} catch (SocketTimeoutException e) {
e.printStackTrace();
}
}
}catch (Exception e) {
e.printStackTrace();
System.out.println(" EXCEPTION " + e.getStackTrace());
}/*catch (IOException e1) {
e1.printStackTrace();
}*/ /*finally {
try {
if (serverSocket != null) {
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}*/
}
}
}
Client Code -
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
public class SimpleClientApp {
public static void main(String[] args) {
new Thread(new SimpleClient()).start();
}
static class SimpleClient implements Runnable {
#Override
public void run() {
Socket socket = null;
try {
socket = new Socket("localhost", 3333);
PrintWriter outWriter = new PrintWriter(socket.getOutputStream(), true);
System.out.println("Wait");
Thread.sleep(20000);
//System.exit(0);
//throw new Exception("Random exception");
//socket.close();
outWriter.println("Hello Mr. Server!");
}catch (SocketException e) {
e.printStackTrace();
}catch (InterruptedException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} /*finally {
try {
if (socket != null)
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
*/ }
}
}
Scenario 1.
Start the server program locally.
Start the Client program locally.
Close the client program abruptly (Ctrl C) - I just get output on
Server program "Client said :null"
Scenario 2.
Start the Server program Locally.
Start the client program locally.
Client is connected to server, Then while client program is waiting close the server program abruptly. Still no exception.
Can some tell me some way I could produce the connection reset exception, With working sample code.
None of the answers above worked for me reliably both on Mac and Linux.
After a lot of Googling, I ended with this article explaining how to do it. Just to be clear: I was trying to reproduce the connection reset from the client side, i.e. "Connection reset by peer".
I tried bringing up a process which run netcat, and abruptly killing the process - that only worked on Mac.
I tried socket.close from another thread, same thread - nothing worked.
Simply, all those methods didn't cause the client to send RST to the server, which causes the exception (reset by peer).
The following worked:
Setup any server - in my case Netty (their getting started Discard server will do).
Use the following client code:
final Socket socket = new Socket("localhost", port);;
socket.setSoLinger(true, 0);
final OutputStream outputStream = socket.getOutputStream();
for (int i=0; i <= 500; i++) {
outputStream.write('a');
}
outputStream.write('\n');
outputStream.flush();
socket.close();
Thread.sleep(2000);
The soLinger() was the magic trick. According to the Oracle article cited above, when you call socket.close() it sends a RST to the other side, instead of sending FIN and then waiting for the other side to finish reading what ever was sent until the FIN - i.e. force close.
It took me 1 day of work to find this out, so I hope it will save you time on your work.
There are several ways. I won't post one of them as it is too much abused, but the simple ways to produce it are:
Close a socket immediately you acquire it, without reading anything. This works if the sender is sending to you rather than reading from you.
If you know the sender has sent something, close the socket without reading it in any way.
This works for me:
class Server {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(9999);
Socket s = ss.accept();
InputStream i = s.getInputStream();
i.read();
}
}
client connects and disconnects without closing socket
class Client {
public static void main(String[] args) throws Exception {
Socket s = new Socket("localhost", 9999);
}
}
this results in exception on server
Exception in thread "main" java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at net.Server.main(Server.java:13)
Instead of provoking this exception using Java client code, I found it easier to just write a short Python script:
import struct, socket
s = socket.socket(socket.AF_INET6)
s.connect(("::1", 8000))
s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
s.close() # provokes Connection Reset at host
This is a problem I never figured out. I've asked many people, and they don't even know. Anyways, lets get to the problem. Here's what I tried to do... Create a client and a server. The client connects to the server, and sends a message to it every 3 minutes (I reduced the time for testing). There has to be two independent threads however (one for the client and server). What I found was, the client would continue to send messages, but the server would no longer listen on port 1234.
Client:
import java.io.PrintWriter;
import java.net.Socket;
public class Client {
public Client(){
startClient();
}
public void startClient(){
new Thread(new Runnable(){
#Override
public synchronized void run(){
try{
Socket sendChat = new Socket("localhost", 1234);
PrintWriter writer = new PrintWriter(sendChat.getOutputStream());
while(true){
Thread.sleep(1000); // normally 180000
writer.println("Hello Server!");
}
}catch(Exception err){
err.printStackTrace();
}
}
}).start();
}
}
Server:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
public class Server {
public Server(){
startServer();
}
public void startServer(){
new Thread(new Runnable(){
#Override
public synchronized void run(){
try{
#SuppressWarnings("resource")
ServerSocket server = new ServerSocket(1234);
while(true){
final Socket test = server.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(test.getInputStream()));
while(!test.isClosed()) {
Date date = new Date();
System.out.println("Server got message from client " + date);
}
reader.close();
}
}catch(Exception err){
err.printStackTrace();
}
}
}).start();
}
}
Start:
public class Start {
public static void main(String[] args){
new Server();
new Client();
}
}
I would greatly appreciate it if someone could tell me what is wrong, because I honestly have no clue.
Write below two lines out of while loop in Server class and it will work for you.
final Socket test = server.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(test.getInputStream()));
What is happening in your code : Server will wait for new client every time after completion of the while loop but there is no client which is going to connected with server at that instance. So server will wait untill a new client will come and server will accept that new client and continue its processing.
you are stack in a loop, try close the connection in the client after the message.
See these links they use
socket.setKeepAlive(true);
java.net.Socket TCP keep-alive usage
and
Permanent and persistent Socket connection in java
Here is the server code
package echoserver;
import java.net.*;
import java.io.*;
public class EchoServer {
public static void main(String[] args) {
try {
//establish server socket
ServerSocket s = new ServerSocket(1981);
//Thread client connectionsincoming
while (true) {
//wait for incoming connection
Socket incoming = s.accept();
Runnable r = new ThreadedEchoHandler(incoming);
Thread t = new Thread(r);
t.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
package echoserver;
import java.net.*;
import java.util.*;
import java.io.*;
class ThreadedEchoHandler implements Runnable {
public ThreadedEchoHandler(Socket i) {
//initializing socket
incoming = i;
}
public void run() {
try {
try {
//recieve input stream from socket
InputStream inStream = incoming.getInputStream();
//recieve output stream from socket
OutputStream outStream = incoming.getOutputStream();
//Create a scanner from input stream
Scanner scan = new Scanner(inStream);
//Create printer writer from output stream and enabled auto flushing
PrintWriter out = new PrintWriter(outStream, true);
//prompt users on how to exit program soon as a long in into the server
out.println("Enter BYE to exit");
boolean done = false;
//while done is not true and scanner has next line loop
while (!done && scan.hasNextLine()) {
//reading text that came in from the socket
String line = scan.nextLine();
//On the server print the ip address of where the text is coming from and the text they typed
System.out.println("Recieved from " + incoming.getInetAddress().getHostAddress() + ": " + line);
//Echo back the text the client typed to the client
out.println("Echo: " + line);
//if they type BYE in caps terminate there connection and I also trimmed whitespaces
if (line.trim().equals("BYE")) {
done = true;
}
}
} //finally close the socket connection
finally {
incoming.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private Socket incoming;
}
and here is the code for client
package client;
import java.net.*;
import java.io.*;
public class Client {
public static void main(String[] args) throws IOException {
PrintWriter out = null;
try {
Socket s = new Socket(InetAddress.getLocalHost(), 1981);
System.out.println("Connected to server on port 1981");
out = new PrintWriter(s.getOutputStream());
out.println("Hello");
s.close();
} catch (Exception ex) {
System.err.println(ex.getMessage());
}
}
}
Socktes are getting created successfully but when control goes to t.start() method call it is not calling run() method of ThreadedEchoHandler class.
Why is this happening? any idea?
The client writes "Hello" to the PrintWriter. So far, so good.
You may expect that the PrintWriter sends this text directly to the socket, but it doesn't. The documentation from the PrintWriter(OutputStream) constructor says that it creates a PrintWriter without automatic line flushing. This means that you have to call out.flush() whenever you want something to be actually sent.
Until you call out.flush() the text only exists in some internal buffer, and the server will not be able to see it.
My guess would be that the acept statement is blocking forever because no client is connecting to the server. You could wrap accept() in prints to prove or disprove.