Asynchronous socket handling in java using the conccurent package still blocks code? - java

I'm trying to play around with the concurrent package and for this reason I tried to write a simple socket handler. Here is the code:
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MultiThreadedServer{
private final static int number_of_threads = 4;
private final static int port = 1134;
public static void main(String[] args){
try{
ServerSocket ss = new ServerSocket(port);
ExecutorService pool = Executors.newFixedThreadPool(number_of_threads);
for(;;){
pool.execute(new SocketHandler(ss.accept()));
}
}catch(Exception e){
System.out.println(e.toString());
}
}
}
class SocketHandler implements Runnable {
private Socket socket;
SocketHandler(Socket s){
this.socket = s;
System.out.println("-- Socket has connected -- ");
}
public void run(){
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String s = "";
while((s = reader.readLine()) != null ){
System.out.println(s);
}
}catch(Exception e){
System.out.println(e.toString());
}
}
}
This code ^^ simply waits for sockets and reads whatever the socket sends. It works fine to an extent. ( I will explain a bit later what bothers me).
The following code is the sender class which "sends" a socket
import java.io.*;
import java.net.*;
public class Sender{
public static void main(String args[]){
try{
int port = Integer.parseInt(args[0]);
Socket socket = new Socket(InetAddress.getByName(null),port);
PrintWriter writer = new PrintWriter(socket.getOutputStream());
writer.write("Wohoo!");
writer.close();
}catch(Exception e){
System.out.println(e.toString());
}
}
}
The code compiles fine and it even runs fine when I run my sender. However if I type
java Sender
about 3 times a second and I try to run it into my console the following thing gets printed:
java.net.BindException: Address already in use
However the whole point of this code was to not block the connections to my port and to queue the tasks. How can I tackle this?

See my comment. But I think what you are seeing is exhausting your tcp ports. Are you running this thing for awhile before it starts printing port already in use? If so read ahead.
So after closing a socket there is a state of TIME_WAIT. Until it passes, you cannot reuse same port unless you have set the socket option SO_REUSEADDR.
So you need to use that option perhaps. See this answer for more insight:
https://stackoverflow.com/a/14388707/520567

Related

Java Client Server Socket Error: java.net.BindException: Address already in use: bind

This is the server side code
I'm pretty sure the error is that the Server Socket Isn't closing the port?
There is no problem when I run the program but, When I run it again I get this Error:
Exception in thread "main" java.net.BindException: Address already in use: bind
at java.base/sun.nio.ch.Net.bind0(Native Method)
at java.base/sun.nio.ch.Net.bind(Net.java:550)
at java.base/sun.nio.ch.Net.bind(Net.java:539)
at java.base/sun.nio.ch.NioSocketImpl.bind(NioSocketImpl.java:643)
at java.base/java.net.ServerSocket.bind(ServerSocket.java:396)
at java.base/java.net.ServerSocket.<init>(ServerSocket.java:282)
at java.base/java.net.ServerSocket.<init>(ServerSocket.java:173)
at internet.server.main(server.java:11)
But if I change the port number it fixes for that one time running. Someone please help also I haven't learned java server sockets or client sockets yet soo I need help as far as I know no one else is having this problem
package internet;
import java.io.IOException;
import java.net.*;
import java.io.*;
public class server {
public static void main(String[] args) throws IOException {
println("Compiled");
ServerSocket ss = new ServerSocket(5502);
Socket s = ss.accept();
println("Client Connected!");
InputStreamReader in = new InputStreamReader(s.getInputStream());
BufferedReader bf = new BufferedReader(in);
String str = bf.readLine();
println("Client: " + str);
s.close();
ss.close();
}
public static void println(String args) {
System.out.println(args);
}
}
This will works fine as long as you terminate your previous execution before you re run it.
Try closing those streams, InputStreamReader and BufferedReader as well. Close them before socket and ServerSocket.
bf.close();
in.close();

BufferedReader readLine() blocking until buffer is full

I'm writing a client/server pair of applications. The server runs multiple threads that collect data and adds it to a BlockingQueue. The socket code loops over the queue and sends whatever data it finds to the client. The data is a string and I append a line separator so that the client can read it using BufferedReader.readLine().
My problem is that instead of readLine() returning on each line that's available it waits until the entire buffer is full before spitting out all the complete lines in the buffer. With the default 8K buffer this means I get data via the client in 8K chunks, which is highly undesirable. I've attached MRE code that represents this. I have confirmed via logging in my actual application that the BufferedWriter is writing the data as soon as it's available from the queue, but to be honest I don't know if the delay is coming after this on the sending side, or is truly on the reading side. If you run the MRE you'll see that the data is displayed approximately 170 lines at a time by the client.
I've searched online for this phenomenon for a couple of days and the one snippet that I could find of a similar issue suggests that maybe it's something to do with the underlying InputStreamReader and/or StreamDecoder, but that is starting to get beyond my expertise. (See this link)
So my question is whether I'm implementing the BufferedReader correctly and how can I resolve the issue I'm seeing so that I get each incoming line without unnecessary delays.
package serverTest;
import java.util.concurrent.BlockingQueue;
public class ServerTest {
public static void main(String[] args) {
int port = 54321;
ServerSocketComms server = new ServerSocketComms(port);
BlockingQueue<String> queue = server.getQueue();
new Thread(server).start();
ClientSocketComms client = new ClientSocketComms("localhost", port);
new Thread(client).start();
for(int i = 0; i < 1000; i++) { // should give about 10 seconds of output
try {
queue.put("" + i + " - All work and no play makes Jack a dull boy");
// Slow things down enough to show what's happening
Thread.sleep(10);
// 48 characters should fill the 8K buffer in approximately 2 seconds
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package serverTest;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class ServerSocketComms implements Runnable {
private final BlockingQueue<String> queue = new LinkedBlockingQueue<>();
private final int port;
public ServerSocketComms(int port) {
this.port = port;
}
#Override
public void run() {
// Open server socket and wait for connection
try {
ServerSocket serverSocket = new ServerSocket(port);
Socket socket = serverSocket.accept();
// Continually loop over blocking data queue until stopped
BufferedWriter dataOut = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
while(socket.isConnected()) {
dataOut.write(queue.take());
dataOut.newLine(); // delimit strings with a line separator
}
// Loop never exits because client socket never completes because of BufferedReader issue
// so sockets never close and application never terminates
socket.close();
serverSocket.close();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
public BlockingQueue<String> getQueue() {
// Return a reference to the sending queue to be populated by other threads
return this.queue;
}
}
package serverTest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class ClientSocketComms implements Runnable {
private final String server;
private final int port;
public ClientSocketComms(String server, int port) {
this.server = server;
this.port = port;
}
#Override
public void run() {
// Open socket to server and wait for incoming data
try {
Socket socket = new Socket(server, port);
BufferedReader dataIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// Continually loop over incoming data until stopped
String data;
while((data = dataIn.readLine()) != null) {
// Should print out every line as it's received,
// but instead waits until buffer is full
// (outputs about 170 lines at a time)
System.out.println(data);
}
// Close socket and thread will die
// (but loop never ends because buffer doesn't get completely refilled)
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Your server is using a BufferedWriter:
BufferedWriter dataOut = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
This one does the buffering that you do not like. It seems the default buffer size is the 8k that you are seeing although that is not documented in the API and could change. Try flushing the buffer using dataOut.flush() if at some point in time you want to ensure everything stored in the buffer so far is sent out to the client immediately. Have a look at the BufferedWriter API for details.
BTW, I have not checked whether there are any other problems in your code. But the above is definitely one.

Parallel processing in Java Sockets not working properly

I have made two different programs for port Scanning. Both the programs use Threads but the thread distribution is different.
The first one uses single thread for single port, so it is not optimized for memory and time.
Here is the code :
import java.net.Socket;
import java.util.Scanner;
import java.lang.Exception;
import java.lang.Thread;
class helper{
public static void main(String []args){
Scanner s= new Scanner(System.in);
int port;
System.out.print("Enter web url :");
String url = s.next();
for(port=0;port<65536;port++){
helper2 h = new helper2(url,port);
h.start();
}
s.close();
}
}
class helper2 extends Thread{
int port;
String url;
helper2(String url,int port){
this.url=url;
this.port=port;
}
private void getStatus(){
try{
Socket skt = new Socket(url,port);
System.out.println(port);
skt.close();
}catch(Exception e){
//Handle Exception here
}
}
public void run(){
getStatus();
}
}
But in the other one I have 256 threads each having performing over 256 ports. It is faster.
Here is the other one :
import java.net.Socket;
import java.lang.Thread;
import java.util.Scanner;
import java.lang.Exception;
class helper {
public static void main(String []args){
Scanner s = new Scanner(System.in);
System.out.printf("Enter url :");
String url = s.next();
for(int i=0;i<256;i++){
helper2 h = new helper2(url,256*i);
h.start();
}
s.close();
}
}
class helper2 extends Thread {
int port ;
String url ;
helper2(String url, int port){
this.port=port;
this.url=url;
}
public void run(){
for(int i=0;i<256;i++){
try {
Socket skt = new Socket(url,i+port);
System.out.println(port+i);
skt.close();
} catch (Exception e) {
//TODO: handle exception
// System.out.print('j'); //for debugging
}
}
}
}
Both are working fine when url is given as localhost. But for other url like www.google.com second program does not behave correctly. Sometimes it does not produce any output and sometimes it throws OutOfMemory error and unable to create more threads. Please help.
Socket(String, int) tries to connect immediately, with no timeout (which means that it waits infinitely if the connection is not accepted by the server). At some hosts (including google.com), a connection to ports that are not specifically open will not be rejected automatically; instead, an attempt of such a connection will hang for some time, until it reaches a client-defined timeout (which is infinite in the case of Socket(String, int)).
I'd use Socket() constructor which does not connect automatically, and then connect manually passing some finite timeout:
Socket socket = new Socket();
socket.connect(new InetSocketAddress("google.com", 8888), 3000);

The constructor ServerSocket(int) is undefined

I am new at JAVA basically I do code in C++. Recently I needed to do something in JAVA socket programming. But I am getting a strange error in ServerSocket(..). I am trying to create a server socket in a particular port. For that my code is like below.
import java.net.*;
import java.io.*;
import java.util.*;
public class ServerSocket {
static ServerSocket socket1;
protected final static int port = 19999;
static Socket connection;
public static void main(String[] args) {
try
{
socket1 = new ServerSocket(port);
}
catch (IOException e) {}
}
}
But I am getting compilation error "The constructor ServerSocket(int) is undefined". Thanks.
Please see my second comment to your original question:
Also, do you have your own class named ServerSocket?
You've named your class ServerSocket and so the Java compiler is looking for the constructor in this class, one that takes an int. Rename that class so you don't have a name conflict and now can use the Java core ServerSocket class.
I suggest a java tutorial first. Just to learn the basic differences.
In short:
In Java everything has to be in a class. You define a static method named 'main'. This is the start of your application.
Here is your example (Filename: DemoClass.java):
import java.net.*;
import java.io.*;
public class DemoClass {
private static ServerSocket socket1;
private static final int port = 19999;
private static void handleConnection(Socket socket) throws IOException {
OutputStream out = socket.getOutputStream();
// Say hello
out.write("Hello World\n".getBytes());
out.flush();
// Close the connection
out.close();
socket.close();
}
// Use this exact method signature!
public static void main(String[] args) {
try {
socket1 = new ServerSocket(port);
// Here is some example what you could do
Socket connection = socket1.accept();
handleConnection(connection);
} catch(IOException e) {
// What should be done if this fails? E.g. port already in use
e.printStackTrace();
}
}
}
But I really suggest a Java and a Java Socket tutorial.
Greetings!
The server program creates the ServerSocket object in a try-with-resources statement:
import java.io.*;
import java.net.*;
class Test{
private static ServerSocket socket1;
private final static int port = 19999;
public static void main (String [] args){
try{
socket1 = new ServerSocket(port);
}
catch(IOException e){
e.printStackTrace();
}
}
}
The constructor for ServerSocket throws an exception if it can't listen on the specified port. for example, the port is already being used.

How to close a server port after we are done using it?

Note: I found a similar question here:
How to close port after using server sockets
But did not find any satisfactory answer there.
Here is my code for the client program:
package hf;
import java.io.*;
import java.net.*;
public class DailyAdviceClient
{
private static final int chatPort = 4242;
public static void main(String[] args)
{
DailyAdviceClient client = new DailyAdviceClient();
client.go();
}
private void go()
{
try
{
Socket socket = new Socket("127.0.0.1",chatPort);
InputStreamReader inputStream = new InputStreamReader(socket.getInputStream());
BufferedReader bufferedReader = new BufferedReader(inputStream);
String advice = bufferedReader.readLine();
System.out.println("Advice received by the client for today is "+advice);
bufferedReader.close();
}
catch(Exception e)
{
System.out.println("Failed to connect to the server");
}
}
}
And here is the code for the server program:
package hf;
import java.io.*;
import java.net.*;
public class DailyAdviceServer
{
private String[] adviceList = {"Take smaller bites",
"Go for the tight jeans. No they do NOT make you look fat.",
"One word: inappropriate",
"Just for today, be honest. Tell your boss what you *really* think",
"You might want to rethink that haircut."};
private static final int chatPort = 4242;
public static void main(String[] args)
{
DailyAdviceServer server = new DailyAdviceServer();
server.go();
}
private void go()
{
try
{
ServerSocket serverSocket = new ServerSocket(chatPort);
while(true)
{
Socket socket = serverSocket.accept();
PrintWriter writer = new PrintWriter(socket.getOutputStream());
String advice = getTodaysAdvice();
writer.println(advice);
writer.close();
}
}
catch(Exception e)
{
System.out.println("Error in establishing connection with the client");
}
}
private String getTodaysAdvice()
{
String advice = null;
int randomIndex = (int) (Math.random()*adviceList.length);
advice = adviceList[randomIndex];
return advice;
}
}
In the application, whenever a client program connects to the server program, it receives a String that contains advice for the day.
When I run
netstat -an
In the command prompt of my Windows computer as suggested in one of the answers in the aforementioned link, I get a message that the port 4242 is
LISTENING
How do I close the port and make it available for future re-use?
To get rid of the LISTENING port you have to call serverSocket.close().
You have to use socket.close() after closing the writer and bufferedReader. So the Port will be free for another communication.

Categories