My TCP Server
public static void main(String argv[]) throws Exception {
ServerSocket server = new ServerSocket(3333);
System.out.println("Server started");
while (true) {
Socket socket = server.accept();
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("Received: " + input.readLine() + "\n");
}
}
My TCP Client.
public static void main(String[] args) throws IOException {
for (int i = 1; i < 50000; i++) {
Socket clientSocket = new Socket("localhost", 3333);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
outToServer.writeBytes(i + "\n");
clientSocket.close();
System.out.println(i);
}
}
The loop in TCP client runs till 16374 and stopped, throwing this exception.
...
...
...
16372
16373
16374
Exception in thread "main" java.net.SocketException: No buffer space available (maximum connections reached?): connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:69)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:157)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:391)
at java.net.Socket.connect(Socket.java:579)
at java.net.Socket.connect(Socket.java:528)
at java.net.Socket.<init>(Socket.java:425)
at java.net.Socket.<init>(Socket.java:208)
at mawia.test.Client.main(Test.java:11)
What is wrong with my code?
Why do I get this error?
How to solve this problem?
Fildor is right, you are creating too many connections or Socket handles, this internally translates to allowed open-file-handles per process which in most probability you are breaking.
Ideal approach would be for client to keep on sending data (50000 records) on one connections i.e. Socket and Server should handle processing this data in a separate thread (So you can run multiple TCP Client concurrently):
TCP Server
public static void main(String argv[]) throws Exception {
ServerSocket server = new ServerSocket(3333);
System.out.println("Server started");
while (true) {
final Socket socket = server.accept();
Thread t = new Thread(new Runnable() {
public void run() {
System.out.println("Server received message from client: ");
BufferedReader input;
try {
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(!socket.isClosed() && socket.getInputStream().available() > 0){
System.out.println("Received: " + input.readLine() + "\n");
}
System.out.println("Client disconnected from server");
} catch (IOException e) {
//break;
}
}
});
t.start();
}
}
TCP Client
public static void main(String[] args) throws IOException {
Socket clientSocket = new Socket("localhost", 3333);
for (int i = 1; i < 50000; i++) {
DataOutputStream outToServer = new DataOutputStream(
clientSocket.getOutputStream());
outToServer.writeBytes(i + "\n");
outToServer.flush();
System.out.println(i);
}
clientSocket.close();
}
Also try once with adding flush() in your TCP Client code before closing the connection, worked with me.
Related
as a part of my homework I have to build two classes one listener and one that is making the requests to the server (the server is already written by my teacher and I don't know how code looks like). In theory: The server that I'm connected to should reply with the exact same requests I sent to him. But in practice I get nothing back.
public class Listenerthread extends Thread {
Socket s;
Scanner answerServer;
public Listenerthread(Socket socket) {
this.s = socket;
this.answerServer = new Scanner(new BufferedReader(new InputStreamReader(s.getInputStream())));
}
public void run() {
System.out.println("Listening to the responses from the server......");
while (true) {
if (answerServer.hasNext()) {
System.out.println(answerServer.nextLine());
}
}
}
}
public class Mainthread {
public static void main(String[] args) throws ParseException {
Socket s = new Socket("someServer", 9999);
Listenerthread server = new Listenerthread(s);
server.start();
if (s.isConnected()) {
System.out.println("Connected");
}
String req = "Heyyy mate"; // server should sent me this back
PrintWriter pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream()));
pw.println(req);
pw.flush();
//pw.close();
//s.close();
}
}
Update: A comment that OP left on the question after I started writing this answer shows that OP does not actually need to handle the server side of the communications. I will leave this answer for now in case it could still be useful.
When you have a client/server model, you should use a ServerSocket on the server side, as you alluded to in your question but then do not appear to have done in your code.
ServerSocket
Here is a ServerSocket example that may clear that up.
ServerSocket serverSocket;
public void serverSocketTest()
{
serverSocket = new ServerSocket(9999);
// each of the below methods will happen on separate threads
new Thread(this::serverSideAcceptConnectionFromClient).start();
new Thread(this::clientSideConnectToServer).start();
}
public void clientSideConnectToServer()
{
try {
System.out.println("Client is trying to connect to server...");
Socket connectionToServer = new Socket("localhost", 9999);
OutputStream thisGoesToTheServer = connectionToServer.getOutputStream();
InputStream thisIsDataComingFromServer = connectionToServer.getInputStream();
System.out.println("Client successfully connected to server.");
} catch(IOException ex) {
System.out.println("Connection to server failed. (" + ex + ")");
}
}
public void serverSideAcceptConnectionFromClient()
{
try {
System.out.println("Server is listening for potential clients...");
Socket connectionFromClient = serverSocket.accept();
InputStream thisIsDataComingFromClient = connectionFromClient.getInputStream();
OutputStream thisIsGoesBackOutToClient = connectionFromClient.getOutputStream();
System.out.println("Server accepted a client");
} catch(IOException ex) {
System.out.println("Error while listening for clients. (" + ex + ")");
}
}
I'm trying to program a Server Client program where the CLIENT will be prompt if the SERVER closes or loses connection. What happens is once I connect the server and the client then disconnects the server it doesn't go to the ConnectException part
example: I opened the Server and Client connects, in the Client it will show that "You are connected to the Server", then if the Server disconnects there should be a "Server is disconnected". and when the Server reopens it will prompt the Client that he's connected to the Server
How can I continuously check if the Server is open or disconnected
here's my code:
SERVER
public class Server
{
private static Socket socket;
public static void main(String[] args)
{
try
{
int port = 25000;
ServerSocket serverSocket = new ServerSocket(port);
//Server is running always. This is done using this while(true) loop
while(true)
{
//Reading the message from the client
socket = serverSocket.accept();
System.out.println("Client has connected!");
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String number = br.readLine();
System.out.println("Message received from client is "+number);
//Multiplying the number by 2 and forming the return message
String returnMessage;
try
{
int numberInIntFormat = Integer.parseInt(number);
int returnValue = numberInIntFormat*2;
returnMessage = String.valueOf(returnValue) + "\n";
}
catch(NumberFormatException e)
{
//Input was not a number. Sending proper message back to client.
returnMessage = "Please send a proper number\n";
}
//Sending the response back to the client.
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(returnMessage);
System.out.println("Message sent to the client is "+returnMessage);
bw.flush();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
CLIENT
public class Client
{
private static Socket socket;
public static void main(String args[])
{
Scanner input=new Scanner(System.in);
try
{
String host = "localhost";
int port = 25000;
InetAddress address = InetAddress.getByName(host);
socket = new Socket(address, port);
System.out.println("Connected to the Server");
}
catch (ConnectException exception)
{
System.out.println("Server is still offline");
}
catch(IOException ex)
{
System.out.println("Server got disconnected");
}
}
}
Well, the best way to tell if your connection is interrupted is to try to read/write from the socket. If the operation fails, then you have lost your connection sometime.
So, all you need to do is to try reading at some interval, and if the read fails try reconnecting.
The important events for you will be when a read fails - you lost connection, and when a new socket is connected - you regained connection.
That way you can keep track of up time and down time.
you can do like this
try
{
Socket s = new Socket("address",port);
DataOutputStream os = new DataOutputStream(s.getOutputStream());
DataInputStream is = new DataInputStream(s.getInputStream());
while (true)
{
os.writeBytes("GET /index.html HTTP/1.0\n\n");
is.available();
Thread.sleep(1000);
}
}
catch (IOException e)
{
System.out.println("connection probably lost");
e.printStackTrace();
}
or you can simply et connection time out like this socket.setSoTimeout(timeout); to check connectivity
or you can use
socket.getInputStream().read()
makes the thread wait for input as long as the server is connected and therefore makes your program not do anything - except if you get some input and
returns -1 if the client disconnected
or what you can do is structure your code in this way
while(isConnected())
{
// do stuffs here
}
So I have my server that looks like this
import java.net.*;
import java.io.*;
public class Server extends Thread {
private ServerSocket serverSocket;
public Server(int port) throws IOException {
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(20000);
}
public void run() {
while(true) {
try {
System.out.println("Waiting for client on port " +
serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to "
+ server.getRemoteSocketAddress());
DataInputStream in =
new DataInputStream(server.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out =
new DataOutputStream(server.getOutputStream());
out.writeUTF("Thank you for connecting to "
+ server.getLocalSocketAddress() + "\nGoodbye!");
server.close();
}catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}catch(IOException e)
{
e.printStackTrace();
break;
}
}
}
public static void main(String [] args) {
int port = 5000;
try {
Thread t = new Server(port);
t.start();
}catch(IOException e) {
e.printStackTrace();
}
}
}
And when I run it, everything goes fine. I also have my client which looks like this.
import java.net.*;
import java.io.*;
public class Client {
public static void main(String [] args) {
String serverName = "Server";
int port = 5000;
try {
System.out.println("Connecting to " + serverName + " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to " + client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF("Hello from " + client.getLocalSocketAddress());
InputStream inFromServer = client.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
System.out.println("Server says " + in.readUTF());
client.close();
}catch(IOException e) {
System.out.println("Error!");
}
}
}
After running my client I get this in the console.
Connecting to Server on port 5000
java.net.UnknownHostException: Server
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:178)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at java.net.Socket.connect(Socket.java:528)
at java.net.Socket.<init>(Socket.java:425)
at java.net.Socket.<init>(Socket.java:208)
at maple.Client.main(Client.java:16)
Line 16 looks like this
Socket client = new Socket(serverName, port);
EDIT:
After changing to a valid server address when I run the code I only get certain statements to run and then it just times out. Why is this?
Waiting for client on port 5000...
Just connected to /127.0.0.1:57355
Hello from /127.0.0.1:57355
Waiting for client on port 5000...
Socket timed out!
The server name is assigned to the String literal "Server" rather than a valid host address.
Its timing out because in constructor you are setting a 20 sec time to live.
serverSocket.setSoTimeout(20000);
Remove this and you should be fine.
My Issue based on code below:
Run TCPServer.java
then Run TCPClient.java
I expect to have the client print out
Server Said(1): HEY DUDE 1
Server Said(2): HEY DUDE 2
... but it just stays on HEY DUDE 1. What am I doing that is not producing the results I want?
TCPServer.java
import java.io.*;
import java.net.*;
class TCPServer {
public static void main (String args[]) throws Exception{
new TCPServer();
}
TCPServer() throws Exception{
//create welcoming socket at port 6789
ServerSocket welcomeSocket = new ServerSocket(6789);
while (true) {
//block on welcoming socket for contact by a client
Socket connectionSocket = welcomeSocket.accept();
// create thread for client
Connection c = new Connection(connectionSocket);
}
}
class Connection extends Thread{
Socket connectionSocket;
Connection(Socket _connectionSocket){
connectionSocket = _connectionSocket;
this.start();
}
public void run(){
try{
//create input stream attached to socket
BufferedReader inFromClient = new BufferedReader(new InputStreamReader (connectionSocket.getInputStream()));
//create output stream attached to socket
PrintWriter outToClient = new PrintWriter(new OutputStreamWriter(connectionSocket.getOutputStream()));
//read in line from the socket
String clientSentence = inFromClient.readLine();
System.out.println("Client sent: "+clientSentence);
//process
String capitalizedSentence = clientSentence.toUpperCase() + '\n';
//write out line to socket
outToClient.print(capitalizedSentence);
outToClient.flush();
}catch(Exception e){}
}
}
}
TCPClient.java
import java.io.*;
import java.net.*;
class TCPClient {
//String name="";
String host = "localhost";
int port = 6789;
Socket socket = null;
public static void main(String args[]) throws Exception{
TCPClient client = new TCPClient();
client.SendToServer("Hey dude 1");
System.out.println("Server Said(1): "+client.RecieveFromServer());
client.SendToServer("Hey dude 2");
System.out.println("Server Said(2): "+client.RecieveFromServer());
client.close();
}
TCPClient(String _host, int _port) throws Exception{
host = _host;
port = _port;
socket = new Socket(host, port);
}
TCPClient() throws Exception{
socket = new Socket(host, port);
}
void SendToServer(String msg) throws Exception{
//create output stream attached to socket
PrintWriter outToServer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
//send msg to server
outToServer.print(msg + '\n');
outToServer.flush();
}
String RecieveFromServer() throws Exception{
//create input stream attached to socket
BufferedReader inFromServer = new BufferedReader(new InputStreamReader (socket.getInputStream()));
//read line from server
String res = inFromServer.readLine(); // if connection closes on server end, this throws java.net.SocketException
return res;
}
void close() throws IOException{
socket.close();
}
}
Your server thread ends as soon as you process first message. You need to put server code into a loop like this:
String clientSentence;
while ((clientSentence = inFromClient.readLine()) != null) {
System.out.println("Client sent: "+clientSentence);
//process
String capitalizedSentence = clientSentence.toUpperCase() + '\n';
//write out line to socket
outToClient.print(capitalizedSentence);
outToClient.flush();
}
The exception is thrown in line 24 the second time I type something (after I have typed the host name) - server works right. Code
import java.io.*;
import java.net.*;
class TCPclient {
public static void main(String[] args) throws Exception {
String hostname, msg;
InetAddress hostaddress;
BufferedReader inFromUser = new BufferedReader (new InputStreamReader(System.in));
System.out.println("Please type host\n");
hostname = inFromUser.readLine(); //I type localhost
hostaddress = InetAddress.getByName(hostname);
Socket cSocket = new Socket(hostaddress, 44444);
String cAddress = cSocket.getLocalSocketAddress().toString();
DataOutputStream outToServer = new DataOutputStream (cSocket.getOutputStream());
while (true)
{
msg = inFromUser.readLine();
System.out.println(msg);
if (msg.equals("exit"))
{
System.out.println("exit");
break;
}
outToServer.writeBytes(cAddress + " said : " + msg + '\n'); //this line throws an exception the second time it runs
}
cSocket.close();
}
}
I am new in java so I am missing something obvious I guess. Exception reads :
Exception in thread "main"
java.net.SocketException: Software
caused connection abort: socket write
error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:115)
at java.io.DataOutputStream.writeBytes(DataOutputStream.java:259)
at TCPclient.main(TCPClient.java:52) Java
Result: 1
Server :
import java.io.*;
import java.net.*;
class TCPServer {
public static void main(String argv[]) throws Exception {
String clientSentence;
ServerSocket welcomeSocket = new ServerSocket(44444);
while(true) {
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(
new InputStreamReader(connectionSocket.getInputStream( ) ) );
clientSentence = inFromClient.readLine();
System.out.println(clientSentence + "\n");
}
}
}
Your client creates one socket and writes over and over again to that one socket. Your server, on the other hand, does this:
ServerSocket welcomeSocket = new ServerSocket(44444);
while(true) {
Socket connectionSocket = welcomeSocket.accept();
That accepts the incoming connection, reads one line, and then abandons it (and I'm guessing on the socket's finalize when being garbage collected it closes the connection). Then it waits for a new connection.
So to fix your immediate problem, try moving
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(
new InputStreamReader(connectionSocket.getInputStream( ) ) );
before the while loop.
How long do you wait between typing second line? It might have something to do with socket being idle.
Also with the server code like this you will see only first message. Try this:
import java.io.*;
import java.net.*;
class TCPServer {
public static void main(String argv[]) throws Exception {
String clientSentence;
ServerSocket welcomeSocket = new ServerSocket(44444);
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
while (true) {
clientSentence = inFromClient.readLine();
System.out.println(clientSentence + "\n");
}
}
}
Try:
while (true)
{
if(inFromUser.readLine() != null)
{
msg = inFromUser.readLine();
System.out.println(msg);
if (msg.equals("exit"))
{
System.out.println("exit");
break;
}
outToServer.writeBytes(cAddress + " said : " + msg + "\n");
}
}
Note the changes:
if(inFromUser.readLine() != null)
{
and
... "\n");
not
... '\n');
Give it a shot. It's probably too simple a solution, but it's something :)