Maximum socket connections available - java

I am trying my hand at socket programming. I built a simple echo server that prints the client text on the screen and sends back a thank you message to the client. However when I run the client (which individually spawns 10000 requests in a loop) sometimes i get "connection refused" exceptions in some client threads. Sometimes all go through without any exception.
Following is my server code :
public class WebServer {
static int hitCount = 0;
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(7777, 10000);
while (true) {
Socket defaultSocket = serverSocket.accept();
new Thread(new ServerSlave(defaultSocket)).start();
System.out.println("Size is :" + hitCount);
}
}
}
class ServerSlave implements Runnable {
Socket clientSocket;
public ServerSlave(Socket socket) {
clientSocket = socket;
WebServer.hitCount++;
}
public void run() {
try {
DataInputStream inputStream = new DataInputStream(clientSocket.getInputStream());
DataOutputStream outputStream = new DataOutputStream(clientSocket.getOutputStream());
System.out.println(inputStream.readUTF());
outputStream.writeUTF("Thank you for contacting the web server");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Following is my client code :
public class Client {
static int excepCount=0;
public static void main(String[] args) throws Exception {
for (int i = 0; i < 10000; i++) {
new Thread(new Worker("" + i)).start();
}
Thread.sleep(10000);
System.out.println( Client.excepCount);
}
}
class Worker implements Runnable {
String clientName;
public Worker(String name) {
clientName = name;
}
public void run() {
System.out.println("Process started for : " + clientName);
Socket socket = null;
try {
socket = new Socket("127.0.0.1", 7777);
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
outputStream.writeUTF("Hello socket. Client number " + clientName + "here");
InputStream inFromServer = socket.getInputStream();
DataInputStream in =
new DataInputStream(inFromServer);
System.out.println("Server says " + in.readUTF());
System.out.println("Closing socket");
} catch (IOException e) {
Client.excepCount++;
e.printStackTrace();
}finally{
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Not sure what I might be doing wrong. Any suggestions ?

You're expecting too much. It just isn't realistic for a client to form 10,000 connections at maximum speed. You're forgetting about the TIME_WAIT state, and the fact that there are only 64k minus several dozen client-side ports available. It isn't a realistic test. If you want to load-test your server you will need quite a few client hosts, or a longer interval between connections.

Related

Why is my message sent only once in Java socket server?

there is a server that is considered to server multiple clients at the same time.
So when clients connects, he is added to clients array. And when server gets the message, it is sent to all the clients.
It works perfectly when one client is connected, but when I have 2 clients at the same time, the message is sent only once, it doesn't work anymore after that. What's the problem?
Server
static DataInputStream inputStream;
static DataOutputStream outputStream;
static ServerSocket serverSocket;
static final int PORT = 3003;
static Socket someClient;
static List<Socket> clients = new ArrayList<>();
public Server()
{
start();
}
public static void main(String[] args) throws IOException
{
try{
serverSocket = new ServerSocket(PORT);
print("Server started on " + serverSocket.getInetAddress().getHostAddress());
while (true)
{
someClient = serverSocket.accept();
new Server();
}
} catch (Exception e){
e.printStackTrace();
}
}
#Override
public void run()
{
try{
clients.add(someClient);
print("Connected from " + someClient.getInetAddress().getHostAddress());
InputStream sin = someClient.getInputStream();
OutputStream sout = someClient.getOutputStream();
inputStream = new DataInputStream(sin);
outputStream = new DataOutputStream(sout);
String message;
while (true)
{
message = inputStream.readUTF();
print(message);
for (int i = 0; i < clients.size(); i++)
{
Socket client = clients.get(i);
OutputStream os = client.getOutputStream();
DataOutputStream oss = new DataOutputStream(os);
oss.writeUTF(message);
}
}
} catch (Exception e){
e.printStackTrace();
}
}
Client
socket = new Socket("0.0.0.0", 3003);
InputStream sin = socket.getInputStream();
OutputStream sout = socket.getOutputStream();
inputStream = new DataInputStream(sin);
outputStream = new DataOutputStream(sout);
sendButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(key != null && key.length() == 16)
{
Date date = new Date();
String msg = ">> " + nickname + ": " + messageField.getText()+" | " + date.getHours()+":"+date.getMinutes()+"\n";
try {
outputStream.writeUTF(Encrypt.AESEncrypt(key, msg));
} catch (IOException e1) {
e1.printStackTrace();
}
messageField.setText("");
}
else if(key == null)
JOptionPane.showMessageDialog(J_Frame, "Your key field is empty");
else if(key.length() != 16)
JOptionPane.showMessageDialog(J_Frame, "Key's length should be 16 symbols");
}
});
while (true)
{
String message;
message = inputStream.readUTF();
append("\n" + Encrypt.AESDecrypt(key, message));
}
} catch (Exception e1) {
clear();
append(">> Unable to connect to the server.");
hideButtons();
}
Every time a client connects to your server, it replaces the previous connection:
while (true)
{
someClient = serverSocket.accept();
...
}
someClient is static:
static Socket someClient;
which means it is shared by all threads.
Also, access to it is not synchronized in any way, which means changes to its value are not guaranteed to be visible to other threads.
As Peter Lawrey pointed out in the comments, the streams also need to be non-static:
static DataInputStream inputStream;
static DataOutputStream outputStream;
actually, the fact that you are always reading from the "latest" inputStream may be the main cause of the behavior you are describing.
outputStream seems to be unused, so it might be best to remove it.
In addition to that, OutputStreams may need to be flushed in order to actually send data.

Java Sockets - EOFException when trying to implement multi-threading

I think it's because when I multi-thread the client&server, the DataOutputStream and DataInputStream buffers I use get overwritten or something like that since the socket can only have 1 duplex connection.
Here's what I have for now:
Client Class in my client program:
public static void main(String args[]) throws UnknownHostException, IOException, InterruptedException {
for (int i=0;i<2;i++) //change limit on i to change number of threads
{
new Thread(new ClientHandler(i)).start();
}
Thread.sleep(10000);
ClientHandler class in my client program:
(Sends a value to the server, the server will echo it back).
public class ClientHandler implements Runnable {
public int clientNumber;
public ClientHandler(int i){
this.clientNumber=i;
}
public void run() {
Socket socket = null;
try {
socket = new Socket("localhost",9990);
System.out.println("connected client number "+clientNumber);
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
DataInputStream input = new DataInputStream(socket.getInputStream());
output.writeDouble((new Random()).nextDouble());
System.out.println(input.readDouble());
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
Server Class in my server program:
ServerSocket socket = new ServerSocket(9990);
try {
while (true) {
Socket threadSocket = socket.accept();
new Thread(new ServerHandler(threadSocket)).start();
Thread.sleep(10000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
finally {
socket.close();
}
}
}
ServerHandler Class in my server program (receives value from client and echoes it back)
public class ServerHandler implements Runnable {
private Socket socket;
public ServerHandler(Socket socket) {
this.socket = socket;
}
public void run() {
while(true) {
try {
DataInputStream input = new DataInputStream(socket.getInputStream());
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
double a = input.readDouble();
output.writeDouble(a);
}catch (IOException e){
e.printStackTrace();
}
}
}
So it's a pretty straight-forward implementation: create multiple threads of the client, and connect them to multiple threads of the server.
Everything works fine until the line:
double a = input.readDouble();
in my ServerHandler class.
I get an EOFException
I'm guessing it's because there can only be a single duplex connection between sockets. But if that's the case then how would I implement multi-threading of sockets at all?
So my question is: how can I get rid of the EOFException and allow myself to perform multi-threaded client-server socket interaction?
(preferably not changing much about my code because it's taken me a long time to get to this point).
The problem is that you share same Socket variable in ServerHandler for all threads:
private static Socket socket
Remove static keyword. Your ServerHandler will be something like this:
public static class ServerHandler implements Runnable {
private Socket socket;
public ServerHandler(Socket socket) {
this.socket = socket;
}
public void run() {
try {
DataInputStream input = new DataInputStream(socket.getInputStream());
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
double a = input.readDouble();
output.writeDouble(a);
} catch (IOException e) {
e.printStackTrace();
}
}
}

I'm trying to send protocol buffer message to server several times but server only got the first one

I'm trying to send protocol buffer message to server several times but server
only got the first one, the output is like this
msgContent:
xxxxxxxxxxxxxxxxxxx
and this thing only show once when I think it should show ten times
anyone can help me ? thanks very much..
//server
public class Main {
public static void main (String[] args) {
Thread serverThread = new Thread() {
private ServerSocket server;
#Override
public void run() {
try {
while(true) {
try {
if (server == null) {
server = new ServerSocket(8080);
}
Socket client = server.accept();
InputStream is = client.getInputStream();
TestProto.Test test = TestProto.Test.parseDelimitedFrom(is);
System.out.println("msgContent: \n" + test.getId());
} catch (Exception ex) {
}
}
} catch (Exception ex) {
}
}
};
serverThread.start();
}
}
///////////////////////////////////////client
public class Client {
private static void sendProtoc(){
try {
TestProto.Test test = TestProto.Test.newBuilder().setId("xxxxxxxxxxxxxxx").build();
Socket socket = new Socket("localhost", 8080);
OutputStream os = socket.getOutputStream();
int msgType = 1;
test.writeDelimitedTo(os);
os.flush();
} catch (Exception ex) {
}
}
public static void main(String[] args) {
for(int i = 0; i < 10; ++i) {
sendProtoc();
System.out.println("sent " + i);
}
}
}

Is it possible to miss a connection?

I'm writing a simple asynchronous tcp server & client program and I am curious if it's possible that the method "waitForConnections" misses a connection because it's still busy with accepting the new connection or start listening to it.
I tested it with 250 clients and I didn't notice a connection loss.
The code i used for testing:
for(int counter = 0; 250 > counter; counter++)
{
final int localCounter = counter;
new Thread(() -> {
try {
Socket socket = new Socket(ip, port);
System.out.println("Connected!");
DataOutputStream out =
new DataOutputStream(socket.getOutputStream());
out.writeUTF("#" + localCounter + " hello server!");
listenToConnection(socket);
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
The server code:
public class Server extends Thread {
private ServerSocket serverSocket;
private final Integer port;
private int amountConnections = 0;
public Server(Integer port) {
this.port = port;
}
public void run() {
startServer(port);
}
private void startServer(Integer port) {
System.out.println("Server started!");
try {
serverSocket = new ServerSocket(port);
waitForConnections();
} catch (IOException e) {
e.printStackTrace();
}
}
private void waitForConnections() {
try {
Socket socket = serverSocket.accept();
System.out.println("New connection from: " + socket.getRemoteSocketAddress() + " - amount connections: " + amountConnections);
amountConnections++;
asyncListenToConnection(socket);
} catch (IOException e) {
e.printStackTrace();
}
finally{
waitForConnections();
}
}
// Creates a new thread for each connection to listen to
private void asyncListenToConnection(Socket socket) {
new Thread(() -> {
while (!socket.isClosed()) {
try {
DataInputStream in =
new DataInputStream(socket.getInputStream());
System.out.println("Connection: " + socket.getRemoteSocketAddress() + " says: " + in.readUTF());
} catch (IOException e) {
closeConnection(socket);
}
}
}).start();
}
private void closeConnection(Socket socket) {
if (!socket.isClosed() || socket.isConnected()) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.println("Connection: " + socket.getRemoteSocketAddress() + " has left");
}
}
}
I'm new to Java, threading and sockets so any tips are welcome including improving the code.
Since you call
serverSocket = new ServerSocket(port);
with no backlog parameter, according to the Oracle Documentation for ServerSocket at:
http://docs.oracle.com/javase/7/docs/api/java/net/ServerSocket.html#ServerSocket%28int%29
The maximum queue length for incoming connection indications (a
request to connect) is set to 50. If a connection indication arrives
when the queue is full, the connection is refused.
You can reduce the chances of this by increasing the backlog. If you also write the client code, you can have clients automatically retry after a connection refused.

How to write A ServerSocket which accept multiple clicent Socket?

I am working on Socket programming. I have build such a server which should accept multiple Clients. Here I have particular num of clients , clients keeps on sending msg to Server every 10sec , Server has to process it.The problem I am having is I am unable to connect multiple Server and here a single client is a continuous running programm in while(true) So if one client Sends a request another client can not connect . Here is my Program.
Server
public class SimpleServer extends Thread {
private ServerSocket serverSocket = null;
private Socket s1 = null;
SimpleServer() {
try {
serverSocket = new ServerSocket(1231);
this.start();
} catch (IOException ex) {
System.out.println("Exception on new ServerSocket: " + ex);
}
}
public void run() {
while (true) {
try {
System.out.println("Waiting for connect to client");
s1 = serverSocket.accept();
System.out.println("Connection received from " + s1.getInetAddress().getHostName());
InputStream s1In = s1.getInputStream();
DataInputStream dis = new DataInputStream(s1In);
String st = dis.readUTF();
System.out.println(st);
s1In.close();
dis.close();
s1.close();
// throw new ArithmeticException();
} catch (IOException ex) {
Logger.getLogger(SimpleServer.class.getName()).log(Level.SEVERE, null, ex);
}
catch (Exception e) {
System.out.println("Exceptiopn: "+e);
}
}
}
public static void main(String args[]) throws IOException {
new SimpleServer();
}
}
Server is working fine but I am not able to write Client program which shoud run in while(true) loop for sending msg to Server and allow other client also connect to Server.
but for a single client I write like this ,
public class SimClient extends Thread {
private Socket s1 = null;
SimClient() {
//this.start();
}
public void run() {
int i=0;
try {
s1 = new Socket("localhost", 1231);
} catch (IOException ex) {
Logger.getLogger(SimClient.class.getName()).log(Level.SEVERE, null, ex);
}
// while (i<10) {
try {
// Open your connection to a server, at port dfg1231
OutputStream s1out = s1.getOutputStream();
DataOutputStream dos = new DataOutputStream(s1out);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter Data from Client:");
String s = br.readLine();
dos.writeUTF(s);
dos.flush();
s1out.close();
dos.close();
// s1.close();
i++;
} catch (IOException ex) {
//ex.printStackTrace();
System.out.println("Exception in While: "+ex.getMessage());
}
//}
}
public static void main(String args[]) throws IOException {
SimClient s= new SimClient();
s.start();
}
}
So can any one help me to write client program. its a great help for me.
just as you have a Thread for the ServerSocket, you need to create a Thread for every Socket returned by serverSocket.accept() , then it loops back around immediately to block and wait to accept another Socket. Make a class called SocketHander which extends Thread and accepts a Socket in the constructor.
public class SocketHandler extends Thread {
private Socket socket;
public SocketHandler(Socket socket) {
this.socket = socket;
}
public void run() {
// use the socket here
}
}
and back in the ServerSocket handler...
for (;;) {
SocketHandler socketHander = new SocketHandler(serverSocket.accept());
socketHander.start();
}
It is generally a good idea to use a Fixed Size Thread Pool because creating Threads in a ad-hoc manner may cause the Server to run out of Threads if the requests are high.
public class SimpleServer extends Thread {
private ServerSocket serverSocket = null;
private static ExecutorService executor = Executors.newFixedThreadPool(100);
SimpleServer() {
try {
serverSocket = new ServerSocket(1231);
this.start();
} catch (IOException ex) {
System.out.println("Exception on new ServerSocket: " + ex);
}
}
public void run() {
while (true) {
try {
System.out.println("Waiting for connect to client");
final Socket s1 = serverSocket.accept();
executor.execute(new Runnable() {
public void run() {
try {
System.out.println("Connection received from " + s1.getInetAddress().getHostName());
InputStream s1In = s1.getInputStream();
DataInputStream dis = new DataInputStream(s1In);
String st = dis.readUTF();
System.out.println(st);
s1In.close();
dis.close();
s1.close();
} catch(Exception e) {
System.out.println("Exceptiopn: "+e);
}
// throw new ArithmeticException();
}});
} catch (IOException ex) {
Logger.getLogger(SimpleServer.class.getName()).log(Level.SEVERE, null, ex);
} catch (Exception e) {
System.out.println("Exceptiopn: "+e);
}
}
}
public static void main(String args[]) throws IOException {
new SimpleServer();
}
}

Categories

Resources