I just started using Sockets, and for my current project I need to be able to control my program from a client, however if my project-partner wants use his client at the same time, the server doesn't send him the "You are connected" message as shown in the connection class. So I assume the server doesn't accept mutiple clients at the same time. I have tried using a Thread of the class Connection, but that also doesn't send the message "You are connected" to the second Client. What am I doing wrong here?
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Listener extends Thread{
private ServerSocket server;
private int PORT;
public boolean running;
public Listener(int port){
try{
this.PORT = port;
this.server = new ServerSocket(PORT,10);
}catch (IOException e) {
System.out.println("Could not create serverSocket...");
}
}
#Override
public void run() {
this.running = true;
try{
waitForConnection();
}catch(IOException e){
System.out.println("Could not accept connection request..");
run();
}
}
public void dispose(){
try{
System.out.println("DISPOSE");
running = false;
server.close();
} catch (IOException i) {
System.out.println("Could not close ServerSocket");
}
}
private void waitForConnection() throws IOException{
while(running){
System.out.println("Waiting for connection");
Socket client = server.accept();
Runnable connection = new Connection(client);
new Thread(connection).start();
}
}
}
This is the Thread I'm using to have multiple users connect at the same time:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class Connection extends Thread {
Socket connection;
private ObjectOutputStream output;
private ObjectInputStream input;
private boolean running;
public Connection(Socket connect){
this.connection = connect;
try {
setupStreams();
whileListening();
} catch (IOException e) {
System.out.println("could not connect to: "+ connection.getInetAddress().getHostName());
}
}
public void dispose(){
try{
output.close();
input.close();
connection.close();
running = false;
}catch(IOException ioException){
ioException.printStackTrace();
}
}
private void whileListening(){
String message = "You are connected! ";
sendMessage(message);
do{
try{
message = (String) input.readObject();
checkMessage(message);
}catch(ClassNotFoundException classNotFoundException){
sendMessage("tf did you send? ");
}catch (IOException e) {
dispose();
run();
}
}while(!message.equals("Client - END") && running == true);
}
private void setupStreams() throws IOException{
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
}
private void sendMessage(String message){
try {
output.writeObject("Server - " + message+"\n");
output.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
private void checkMessage(String text){
//check the message
}
}
EDIT: Addittional information
Before the first client connects, the server console says "Waiting for connection", then when the first client connects, the client console says "You are connected" and, when a second client connects, the console is black, when I close the first client, the second client console says "You are connected" and the server console says "Waiting for connection", then if I close the second client aswell, the server console says "Waiting for connection" again.
In your constructor of the public class Connection extends Thread you do this whileListening()stuff, so your constructor never ends, you need to override the run() function and do that there
#Override
public void run() {
while(true) {
try {
whileListening();
} catch(Exception e) {}
}
}
like so, it should do the trick.
I think you must accept first, after that you start the thread.
For example, let's suppose something like this
in your main class, you get the ServerSocketFactory and then the ServerSocket.
then, inside an (endless) loop, you wait for a new Socket returned by the ServerSocket.accept()
Only after that, you start your thread
Here's an example from a SSLServerSocket, which is pretty much the same logic (consider it a pseudo-code)
SSLContext sc = SSLContext.getInstance("TLS");
(...)
SSLServerSocketFactory ssf = sc.getServerSocketFactory();
SSLServerSocket s = (SSLServerSocket) ssf.createServerSocket(portNumber);
while (listening) {
SSLSocket c = (SSLSocket) s.accept();
log.info("Serving");
new SimpleSSLServerSocketThread(c).start();
}
Related
so today I've tried to install Citadel Email server on a raspberry pi which went ok but unfortunantly I cannot reach it from outside LAN.
I've tried to pinpoint the problem and use scanner tools that look for open ports like these :https://www.whatsmyip.org/port-scanner/
I've verified that my public IP adress is the same as my domain returns. Which indeed it is.
I've checked port forwarding severel times.
Last but not least I've wrote this java code to have a really simple example:
package main;
import java.io.IOException;
public class Main {
public static void main(String... args){
try {
Server server = new Server(8080);
Client client = new Client(8080);
} catch (IOException e) {
e.printStackTrace();
}
}
}
package main;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
private boolean stop = false;
public Server(int port) throws IOException {
ServerSocket serverSocket = new ServerSocket(port);
Runnable runnable = new Runnable() {
#Override
public void run() {
while(stop == false) {
try {
Socket socket = serverSocket.accept();
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
outputStream.writeUTF("Hello World!");
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
String input = inputStream.readUTF();
System.out.println("Client wrote: " + input);
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(runnable, "server executor");
thread.start();
}
public void stop(){
this.stop = true;
}
}
package main;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
public class Client {
public static final String LOCALHOST = "localhost";
public static final String KIRAZUKE = "---";
public static final String PUBLIC_IP_4 = "---";
public Client(int port) {
try{
doTest(LOCALHOST, port);
} catch (IOException e) {
e.printStackTrace();
}
try{
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
try{
doTest(KIRAZUKE, port);
} catch (IOException e) {
e.printStackTrace();
}
try{
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
try{
doTest(PUBLIC_IP_4, port);
} catch (IOException e) {
e.printStackTrace();
}
}
private void doTest(String host, int port) throws IOException {
System.out.println("Opening to: " + host);
Socket socket = new Socket(host, port);
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
outputStream.writeUTF("Hello dear Server ... calling from " + host + " ... over.");
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
String string = inputStream.readUTF();
System.out.println("Response from server after " + host + " call: " + string);
}
}
So I've replaced the domain name and my public ip with dashes for privacy reasons. But what happens is that when using the localhost connection everything works fine the server prints the text sent by the client and vise versa. While using either the public IP or Domain name it fails due to time out.
What could be reasons that any incoming traffic is blocked altough port forwarding is enabled for the 8080 port (and other ports that I tried) ?
Note: I've also called my ISP, according to them they "don't block anything". Additionally I tried port forwarding port 3389 and tried remote desktop to my pi but that also failed.
Thanks in advance :)
This question already has an answer here:
java.net.SocketException: socket closed TCP Client Server Communication [duplicate]
(1 answer)
Closed 5 years ago.
This is the first java socket/multithreaded application that I write, therefore I would like to apologize for the atrocious code that you are about to witness.
Anyway, most of you will probably regard this code as being basic, a standard server that allows connection from more clients at a time. Also, the server has an interface with just a StopServer button, which closes the server, meanwhile the Client doesn't do anything else than just connect to the server and then disconnect afterwards.
Now, if I simply run the server class, it's ok, nothing 'bad' happens and when I close it, it closes fine, however:
1: If I run the server class, and then I run the client class once, let the client disconnect, and then try to close the server, I get the error:
java.net.SocketException: socket closed
2: Each client will add about ~30-35% of CPU utilization in just a brief run, and that utilization will remain at the "Java(TM) Platform SE Binary" process, for as long as the server continues to run. If I let a client be connected to the server for, let's say 30 seconds, the CPU utilization will reach 100%.
Also, I did a little research and I know that the "socket closed exception" means that you closed the socket, and then continued to try to use it, and also there's probably something wrong with how the server handles the disconnected clients.
Here's the code:
Server
import java.sql.*;
import java.net.*;
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Server extends JFrame
{ private Connection con;
private static int port = 44444;
private boolean serverKeepGoing;
private static int uniqueId;
private ArrayList<ClientThread> al;
private ServerSocket serverSocket;
public Scanner keyboard = new Scanner(System.in);
public static void main(String[] args) throws IOException
{ Server server = new Server(port);
server.start();
}
public void ServerClose()
{
serverKeepGoing = false;
try
{
for(int i = 0; i < al.size(); ++i)
{ ClientThread tc = al.get(i);
try
{
tc.in.close();
tc.out.close();
tc.socket.close(); }
catch(IOException e) { e.printStackTrace(); }
serverSocket.close();}
}catch(Exception e) { e.printStackTrace(); }
}
public Server (int port)
{
serverInterface();
al = new ArrayList<ClientThread>();
}
public void start()
{ serverKeepGoing = true;
try
{ serverSocket = new ServerSocket(port);
System.out.println("Server is running!");
while(serverKeepGoing)
{ Socket socket = serverSocket.accept(); // accept connection. LINE 65
// ^ALSO :java.net.SocketException: socket closed
// if I was asked to stop
if(!serverKeepGoing)
{ ServerClose(); break;}
ClientThread t = new ClientThread(socket); // make a thread of it
al.add(t); // save it in the ArrayList
t.start();
}
ServerClose(); // means the server has got to be closed
}catch (IOException e) { e.printStackTrace(); System.out.println("Error in method start"); }
}
public synchronized void remove(int id) {
// scan the array list until we found the Id
for(int i = 0; i < al.size(); ++i) {
ClientThread ct = al.get(i);
// found it
if(ct.id == id) {
al.remove(i);
return;
}
}
}
class ClientThread extends Thread
{ // the socket where to listen/talk
Socket socket;
BufferedReader in;
PrintWriter out;
boolean clientKeepGoing;
// my unique id (easier for deconnection)
int id;
public ClientThread(Socket socket)
{ id = ++uniqueId;
this.socket = socket;
try
{
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
}
catch (IOException e) { return; }
}
public void run()
{
boolean clientKeepGoing = true;
while(clientKeepGoing)
{ try
{
}catch(Exception e){ e.printStackTrace(); }
}
// remove myself from the arrayList containing the list of the
// connected Clients
remove(id);
close();
}
// try to close everything
private void close()
{ clientKeepGoing = false;
try {
if(out != null) out.close();
}
catch(Exception e) {}
try {
if(in != null) in.close();
}
catch(Exception e) {};
try {
if(socket != null) socket.close();
}
catch (Exception e) {}
}
}
public void serverInterface(){
JFrame frame = new JFrame("Server");
frame.setLayout(null);
int windowWidth = 300;
int windowHeight = 400;
frame.setBounds(250, 150, windowWidth, windowHeight);
JButton stopServer = new JButton("Stop server");
stopServer.setFocusable(false);
stopServer.setBounds(60, 275, 175, 20);
frame.add(stopServer);
stopServer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
ServerClose();
System.exit(1);
}
});
frame.setResizable(false);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setVisible(true);
}
public void windowClosing(WindowEvent e)
{ ServerClose();
System.exit(1);
}
public void windowClosed(WindowEvent e) {}
public void windowOpened(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
}
The 'java.net.SocketException: socket closed' is on line 65 of the code above.
Client
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
public class Client
{ private BufferedReader in;
private PrintWriter out;
private Socket socket;
private int port;
private String server;
public static void main(String[] args)
{ int portNumber = 44444;
String serverAddress = "localhost";
Client client = new Client(serverAddress, portNumber);
if(!client.start())
return;
}
public Client(String server, int port)
{ this.server = server;
this.port = port;
}
public boolean start()
{ // try to connect to the server
try {
socket = new Socket(server, port);
}
// if it failed not much I can do
catch(Exception ec) {
System.out.println("Error connectiong to server:" + ec);
ec.printStackTrace();
return false;
}
try
{
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);;
}
catch (IOException eIO) {
System.out.println("Exception creating new Input/output Streams: " + eIO);
eIO.printStackTrace();
return false;
}
// creates the Thread to listen from the server
new ListenFromServer().start();
// success we inform the caller that it worked
return true;
}
class ListenFromServer extends Thread
{
public void run()
{ while(true)
{
disconnect() ;
break;
}
}
}
public void disconnect()
{ try {
if(in != null) in.close();
}
catch(Exception e) {} // not much else I can do
try {
if(out != null) out.close();
}
catch(Exception e) {} // not much else I can do
try{
if(socket != null) socket.close();
}
catch(Exception e) {} // not much else I can do
}
}
Note that this is just a fragment of the whole application that I am currently building, I tried to post only what had to do with the Server-Client communication, so I deleted everything else, I'm saying this in case you see something that maybe doesn't have any purpose, I probably omitted to delete it
I see that the question got marked as duplicate, which I consider to be unfair. Firstly, in the 'similar' question, the problem was obvious, the outpot stream was closed, which closed the socket, but the socket had still been used, meanwhile, my program closes everything alltoghether and also has the CPU problem I mentioned, for which I cannnot get any answer from the so called 'similar' question.
The high CPU utilization is because your client threads aren't doing anything else besides burning the CPU with their empty loops. As for the SocketException, it works as planned, so catch it and handle it.
Scenario:
a) Persistent connections
b) Manage each server-client communication individually
c) Protect System from propagating exceptions/errors
I tried to created two instances of server socket listeners using the following code :
SimpleSocketServers.java
public class SimpleSocketServers {
public static void main(String[] args) throws Exception {
int port1 = 9876;
SimpleSocketServer server1 = new SimpleSocketServer(port1);
server1.startAndRunServer();
System.out.println("Servers : server1 Listening on port: " + port1);
int port2 = 9875;
SimpleSocketServer server2 = new SimpleSocketServer(port2);
server2.startAndRunServer();
System.out.println("Servers : server2 Listening on port: " + port2);
}
}
and
SimpleSocketServer.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class SimpleSocketServer {
private ServerSocket serverSocket;
private int port;
public SimpleSocketServer(int port) {
this.port = port;
}
public void startAndRunServer() {
try {
System.out.println("Starting Server at port " + port + " ...");
serverSocket = new ServerSocket(port);
System.out.println("Listening for client connection ...");
Socket socket = serverSocket.accept();
RequestHandler requestHandler = new RequestHandler(socket);
requestHandler.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class RequestHandler extends Thread {
private Socket socket;
RequestHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
System.out.println("Client Request Response being processed...");
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
}
But, it creates only one instance as control is not returning from the constructor of first instance. Is there any possibility to get back control and run both instances of server socket listeners simultaneously? (ps: Pardon me, if it is wrong or trivial!)
Use 2 Different Threads, Listening To 2 Different Ports.
Thread ServerThread1 = new Thread(new Runnable() {
#Override
public void run() {
ServerSocket ServerSocketObject = null;
while(true)
{
try {
ServerSocketObject = new ServerSocket(Your_Port_Number1);
Socket SocketObject = ServerSocketObject.accept();
// Your Code Here
SocketObject.close();
} catch (IOException e) {
try {
ServerSocketObject.close();
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
});
Thread ServerThread2 = new Thread(new Runnable() {
#Override
public void run() {
ServerSocket ServerSocketObject = null;
while(true)
{
try {
ServerSocketObject = new ServerSocket(Your_Port_Number2);
Socket SocketObject = ServerSocketObject.accept();
// Your Code Here
SocketObject.close();
} catch (IOException e) {
try {
ServerSocketObject.close();
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
});
ServerThread1.start();
ServerThread2.start();
You need to have SimpleSocketServer implement Runnable; start a thread with itself as the Runnable in the constructor; and run an accept() loop in the run() method. At present you're blocking in the constructor waiting for a connection, and your servers will also only handle a single connection.
The more interesting question is why you want to provide the same service on two ports.
I have the following code for sending data over a socket:
socketclient.java
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
public class SocketClient
implements Runnable
{
private Socket socket;
private String ServerIP = "192.168.0.11";
private static final int ServerPort = 7000;
#Override
public void run()
{
try
{
socket = new Socket(ServerIP, ServerPort);
}
catch(Exception e)
{
System.out.print("Whoops! It didn't work on ip" + ServerIP + "!:");
System.out.print(e.getLocalizedMessage());
System.out.print("\n");
}
}
public void Send(String s)
{
try
{
Thread.sleep(10);
OutputStream out = socket.getOutputStream(); //Starts the output stream
PrintWriter output = new PrintWriter(out);
output.println(s); //sends the data over the socket
output.flush(); //flushes the outputwriter
output.close(); //closes the outputwriter
out.close(); //closes the outputstream
}
catch (UnknownHostException e) {
System.out.print(e.toString());
} catch (IOException e) {
System.out.print(e.toString());
}catch (Exception e) {
System.out.print(e.toString());
}
}
}
When i dont have the sleep in the send function the server output looks like this (i have it set to print the 'conn' and 'addr' of every connection), the server is coded in python
Connected with 192.168.0.11:52578
in client thread
Connected with 192.168.0.11:52579
in client thread
Connected with 192.168.0.11:52609
in client thread
and the server connection data recieveing/main connection thread is this:
def clientthread(conn):
#Sending message to connected client
#Receiving from client
data = conn.recv(4096)
print data
#came out of loop
conn.close()
My goal for the server is to open/close sockets on the client-side everytime i want to send data because i want each reciever to create its own connections using a socket class i created.
What is the reason for having to add a thread.sleep() before sending a string over a TCP socket in java?
Also, this is how i use my Socketclient class:
SMSClient = new SocketClient();
Thread thread = new Thread(SMSClient);
thread.start();
SMSClient.Send(smsData);
When you instantiate a new SocketClient object you are not running the new thread. You should call your Send(String s) method just after socket = new Socket(ServerIP, ServerPort); from inside the run method.
To know the current thread in your running code put some log like the following: Log.d("label", "thread id: "+android.os.Process.myTid()). Try for example to evaluate the current thread inside run method, and inside the Send(String s) method when you call this latter as you are doing and after having moved the call to the method inside the run.
I suggest to use IntentService for your purpose since, when needed, you can managed easily the socket connection and transmission in a separate thread.
When the thread.start() call returns the thread may not have executed yet. And then you are sending already your first request. You may wait with sleep after thread.start() that is better (while sleeping in the main thread the connection thread has a chance to run) - but still not best practice. Here is my working code ( I added a main function to the SocketClient ):
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
public class SocketClient
implements Runnable
{
private Socket socket;
private String ServerIP = "127.0.0.1";
private static final int ServerPort = 7000;
#Override
public void run()
{
try
{
socket = new Socket(ServerIP, ServerPort);
}
catch(Exception e)
{
System.out.print("Whoops! It didn't work on ip" + ServerIP + "!:");
System.out.print(e.getLocalizedMessage());
System.out.print("\n");
}
}
public void Send(String s)
{
try
{
OutputStream out = socket.getOutputStream(); //Starts the output stream
PrintWriter output = new PrintWriter(out);
output.println(s); //sends the data over the socket
output.flush(); //flushes the outputwriter
output.close(); //closes the outputwriter
out.close(); //closes the outputstream
}
catch (UnknownHostException e) {
System.out.print(e.toString());
} catch (IOException e) {
System.out.print(e.toString());
}catch (Exception e) {
System.out.print(e.toString());
}
}
static public void main(String[] args)
{
SocketClient socketClient = new SocketClient();
Thread thread = new Thread(socketClient);
thread.start();
try
{
Thread.sleep(19);
}
catch(Exception e) {}
socketClient.Send("hallo");
}
}
So I don't know who to go about creating a multithreaded server. I have client and server working fine together but can't introduce multiple clients properly. Here is my Server code:
package dod;
import java.net.*;
import java.io.*;
import dod.game.GameLogic;
public class Server{
Server(GameLogic game, int port) throws IOException{
ServerSocket ss = null;
Socket sock = null;
try{
ss = new ServerSocket(4444);//port no.
while(true){
try{
sock = ss.accept();
ClientThread thread = new ClientThread(game, sock);
System.out.println("Adding new player...");
thread.run();
}catch(final Exception e) {
System.err.println(e.getMessage());
System.exit(1);
}
}
}catch(Exception d){
System.out.println(d);
}finally{
if(ss!=null){
ss.close();
}
}
}
}
Here is my thread class:
package dod;
import java.io.*;
import java.net.Socket;
import dod.game.GameLogic;
import dod.game.PlayerListener;
public class ClientThread extends CommandLineUser implements PlayerListener, Runnable{
DataInputStream in;
PrintStream out;
// The game which the command line user will operate on.
// This is private to enforce the use of "processCommand".
ClientThread(GameLogic game, Socket sock) {
super(game);
try{
in = new DataInputStream(sock.getInputStream());
out = new PrintStream(sock.getOutputStream());
}catch(IOException ioe){
System.out.println(ioe);
}
game.addPlayer(this);
}
/**
* Constantly asks the user for new commands
*/
public void run() {
System.out.println("Added new human player.");
// Keep listening forever
while(true){
try{
// Try to grab a command from the command line
final String command = in.readLine();;
// Test for EOF (ctrl-D)
if(command == null){
System.exit(0);
}
processCommand(command);
}catch(final RuntimeException e){
System.err.println(e.toString());
System.exit(1);
} catch (final IOException e) {
System.err.println(e.toString());
System.exit(1);
}
}
}
/**
* Outputs a message to the player
*
* #param message
* the message to send to the player.
*/
public void outputMessage(String message) {
out.print(message);
}
}
Not asking for new code as such, just need pointers as to what I need to do have multiple client connection at the same time! Thanks to anyone who helps out!
To start, add new Thread(clientThread) in the server and call start() on it - as is everything's happening on the same thread.
public class Server{
Server(GameLogic game, int port) throws IOException{
ServerSocket ss = null;
Socket sock = null;
try{
ss = new ServerSocket(4444);//port no.
while(true){
try{
sock = ss.accept();
ClientThread thread = new ClientThread(game, sock);
System.out.println("Adding new player...");
thread.start(); //you have to use start instead of run method to create multi thread application.
}catch(final Exception e) {
System.err.println(e.getMessage());
System.exit(1);
}
}
}catch(Exception d){
System.out.println(d);
}finally{
if(ss!=null){
ss.close();
}
}
}
}
You have to use start instead of run method to create multi thread application.
If you want to send messages about new connections you have to hold sock in a list and when a new connection accepted send message to all socket object in list. (server broadcasts to all connected sockets)
I hope it helps.