In socket programming using Java.I want a function call to happen whenever a client connects to the server. I'm stuck up here. Any help will be appreciated.
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class NewConnectionListener implements Runnable{
public static ServerSocket serverSocket;
public NewConnectionListener(){
try {
serverSocket = new ServerSocket(500);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
while(true){
try {
Socket s = serverSocket.accept();
callMethodWithNewSocket(s);
System.out.println("new Client");
} catch (IOException e) {
System.out.println("Error getting Client");
e.printStackTrace();
}
}
}
}
With this code everytime there is a new connection to port 500 on the server the method callMethodWithNewSocket(Socket s) will be called with the socket as a parameter.
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 :)
I have a client-server app.
It opens a socket on client side, then I input data to send, it's also sent to other clients, but then the socket is closed. Why? I have tried many different approaches, like shifting din and dout to thread itself, adding some handlers, etc. But no progress yet.
I saw some other problems like this, but the solutions there are not applicable to my problem (I am not so experienced in sockets). Would like a solution to my specific problem.
Errors:
java.net.SocketException: Socket is closed
at java.base/java.net.Socket.getInputStream(Socket.java:927)
at com.uniqueapps.network.ClientThread.lambda$run$1(ClientThread.java:23)
at java.base/java.lang.Thread.run(Thread.java:833)
java.net.SocketException: Socket is closed
at java.base/java.net.Socket.getOutputStream(Socket.java:998)
at com.uniqueapps.network.ClientThread.lambda$run$0(ClientThread.java:28)
at java.base/java.lang.Thread.run(Thread.java:833)
Exception in thread "Thread-2" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1013)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:967)
at com.uniqueapps.network.ClientThread.lambda$run$0(ClientThread.java:27)
at java.base/java.lang.Thread.run(Thread.java:833)
Server.java codes:
package com.uniqueapps.network;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
public class Server {
final static int PORT = 5555;
static ServerSocket serverSocket;
static ArrayList<ClientThread> clients = new ArrayList<>();
public static void main(String[] args) {
try {
serverSocket = new ServerSocket(PORT);
new Thread(() -> {
while (true) {
try {
Socket clientSocket = serverSocket.accept();
ClientThread client = new ClientThread(clientSocket);
client.run();
clients.add(client);
System.out.println("New client joined: " + client.socket.getLocalPort());
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
ClientThread.java codes:
package com.uniqueapps.network;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
public class ClientThread implements Runnable {
Socket socket;
public ClientThread(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
new Thread(() -> {
boolean run = true;
while (run) {
try (DataInputStream din = new DataInputStream(socket.getInputStream())) {
String text = din.readUTF();
if (!text.equals("")) {
new Thread(() -> {
for (ClientThread clientThread : Server.clients) {
try (DataOutputStream dout = new DataOutputStream(clientThread.socket.getOutputStream())) {
dout.writeUTF(text);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
} catch (EOFException ignored) {
} catch (SocketException e) {
e.printStackTrace();
Server.clients.remove(this);
run = false;
System.out.println("Client left: " + socket.getLocalPort());
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
Client.java codes:
package com.uniqueapps.network;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost", 5555);
socket.setKeepAlive(true);
new Thread(() -> {
try {
DataOutputStream dout = new DataOutputStream(socket.getOutputStream());
Scanner scn = new Scanner(System.in);
while (true) {
String text = scn.nextLine();
if (!text.equals("")) {
try {
dout.writeUTF(text);
} catch (IOException e) {
e.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
DataInputStream din = new DataInputStream(socket.getInputStream());
while (true) {
try {
String text = din.readUTF();
if (!text.equals("")) {
System.out.println(text);
}
} catch (EOFException ignored) {
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Edit:
Thanks to Michael Lee, i understood the problem i have been trying to understand for weeks. I remade the code, but i am stuck a place.
I got to know that the .run(); method of "runnable" halts the current thread, but .start(); of "thread" doesn't. So i removed threads from all places, except one. This place is still getting the "Socket closed" error (If i keep runnable here, then the thread is halted, and the message not relayed to other clients). How can i overcome this?
Server.java:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
public class Server {
final static int PORT = 8686;
static ServerSocket serverSocket;
static ArrayList<ClientThread> clients = new ArrayList<>();
public static void main(String[] args) {
try {
serverSocket = new ServerSocket(PORT);
System.out.println("Server ready! Running on port " + PORT);
while (true) {
try {
Socket clientSocket = serverSocket.accept();
System.out.println("New client joined: " + clientSocket.getPort());
ClientThread client = new ClientThread(clientSocket);
System.out.println("Created thread for client.");
clients.add(client);
System.out.println("Added client to list.");
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
ClientThread.java:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
public class ClientThread extends Thread {
Socket socket;
public ClientThread(Socket socket) {
this.socket = socket;
this.start();
System.out.println("Started thread for client.");
}
#Override
public void run() {
try {
boolean run = true;
DataInputStream din = new DataInputStream(socket.getInputStream());
while (run) {
try {
String text = din.readUTF();
if (!text.equals("")) {
for (ClientThread clientThread : Server.clients) {
try (DataOutputStream dout = new DataOutputStream(clientThread.socket.getOutputStream())) {
dout.writeUTF(text);
} catch (IOException e) {
e.printStackTrace();
}
}
}
} catch (EOFException ignored) {
} catch (SocketException e) {
e.printStackTrace();
Server.clients.remove(this);
run = false;
System.out.println("Client left: " + socket.getPort());
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Client.java:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
public class ClientThread extends Thread {
Socket socket;
public ClientThread(Socket socket) {
this.socket = socket;
this.start();
System.out.println("Started thread for client.");
}
#Override
public void run() {
try {
boolean run = true;
DataInputStream din = new DataInputStream(socket.getInputStream());
while (run) {
try {
String text = din.readUTF();
if (!text.equals("")) {
for (ClientThread clientThread : Server.clients) {
try (DataOutputStream dout = new DataOutputStream(clientThread.socket.getOutputStream())) {
dout.writeUTF(text);
} catch (IOException e) {
e.printStackTrace();
}
}
}
} catch (EOFException ignored) {
} catch (SocketException e) {
e.printStackTrace();
Server.clients.remove(this);
run = false;
System.out.println("Client left: " + socket.getPort());
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
In your ClientThread, after din.readUTF(); if (!text.equals("")) { ..., you should directly start processing the incoming data in current thread, rather than initializing a new thread to handle them.
Because in you current thread, the one holding the connected socket, probably closed before the new thread has not even started up. As Java Docs says:
void close() throws Exception
Closes this resource, relinquishing any underlying resources. This method is invoked automatically on objects managed by the try-with-resources statement.
That is why you got Socket Closed exceptions.
One more thing is that, there are too many threads in either Server or Client. Most of time such things are unnecessary, say, for a rather simple application. Because they are not quite managed well in your codes, which more likely makes your program behave unexpectedly in the future. Try use threads only if necessary, instead of using them as much as possible.
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();
}
My final project for a class is to put together a game, including multiplayer. So I started trying to figure out java networking, and I'm kind of stuck.
Each of the two game clients needs to be able to send and receive messages to and from the other client.
The way I figured I would handle this is that I have a NetworkServer and NetworkClient objects that runs in their own threads.
I was thinking that I would just start them from my main game application, but I wanted to do some testing first, so I set this project up:
NetworkClient:
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Timer;
import java.util.TimerTask;
public class NetworkClient extends Thread {
Socket server;
ObjectOutputStream out;
Timer timer;
public NetworkClient(String hostname, int port) throws IOException
{
server = new Socket(hostname, port);
out = new ObjectOutputStream(server.getOutputStream());
timer = new Timer();
timer.schedule(new SendTask(), 0, 1*1000);
}
public void sendData(Integer b) throws IOException {
out.writeObject(b);
}
class SendTask extends TimerTask {
Integer i = new Integer(1);
public void run() {
System.out.println("Client: Sending Integer: " + i.toString());
try {
sendData(i);
i = new Integer(i.intValue()+1);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} // run()
} // class SendTask
}
NetworkServer:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
public class NetworkServer extends Thread {
private ServerSocket serverSocket;
private Socket client;
private Integer i;
private ObjectInputStream in;
public NetworkServer(int port) throws IOException
{
serverSocket = new ServerSocket(port);
//serverSocket.setSoTimeout(10000);
}
public void run()
{
try {
System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
client = serverSocket.accept();
System.out.println("Just connected to " + client.getRemoteSocketAddress());
in = new ObjectInputStream(client.getInputStream());
} catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
while(true)
{
try
{
i = (Integer) in.readObject();
System.out.println("Server: Received the integer: " + i.toString());
}
catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}
catch(IOException e)
{
e.printStackTrace();
try { client.close();} catch (IOException e1) {}
break;
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Network (The thing I'm using to try and test this):
import java.io.IOException;
public class Network {
NetworkClient client;
NetworkServer server;
public Network() throws IOException {
server = new NetworkServer(6066);
server.start();
client = new NetworkClient("192.168.1.196", 6066);
client.start();
}
public static void main(String [] args)
{
try
{
Network n = new Network();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
I have the timer in there to facilitate sending data from the client to the server, which would normally be done by my game, but since I'm testing I had to have it send somehow.
When I run this where the client and server are talking to each other, I get both the Sent and Received messages.
When I put it on my laptop (and change the IP in NetworkClient to match my desktop, and vice versa on my desktop) and run it in both places, the client on the desktop sends to the server on the laptop, but the client on the laptop does not send to the server on the desktop.
And at some point during the running, I get an exception about that client's connection being reset by peer, though the working client/server connection continue.
So, I guess my question is, Does anyone know why it works in one direction but not bidirectionally?
FIXED!!
Edit: Gah, I figured it out. It had to do with the timing on starting the two servers.
I changed Network to:
import java.io.IOException;
public class Network {
NetworkClient client;
NetworkServer server;
public Network() throws IOException {
startServer();
startClient();
}
private void startServer() throws IOException {
server = new NetworkServer(6066);
server.start();
}
private void startClient(){
boolean isConnected = false;
while (!isConnected) {
try {
client = new NetworkClient("192.168.1.196", 6066);
} catch (IOException e) {
// TODO Auto-generated catch block
//e.printStackTrace();
continue;
}
isConnected = true;
}
client.start();
}
public static void main(String [] args)
{
try
{
Network n = new Network();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
Edit your Firewall. Make sure that java.exe has inbound and outbound traffic enabled. Also, add a rule to your Firewall for port 6066.
im making a server for an application, and I made a thread for accepting user's.
but it seems that it doesn't come to my overrided method run()
it doesn't give me an error or such it just doesn't run.
Here is the code:
This is the Client listener
package org.walking.server.listener;
import java.io.IOException;
import java.net.ServerSocket;
import javax.swing.SwingWorker;
/*
* Walking client listener!
*/
public class WalkingCL {
private SwingWorker work;
ServerSocket server;
public boolean listening = true;
public void acceptclient(){
try {
System.out.println("Created server socket");
server = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Error while creating ServerSocket on port 4444");
e.printStackTrace();
}
work = new SwingWorker<Object,Void>(){
public Object doInBackground(){
while(listening){
try {
new WalkingCLT(server.accept()).start();
} catch (IOException e) {
System.err.println("Error while making thread!");
e.printStackTrace();
}
}
return listening;
}
};
}
}
Here is the client listener thread:
package org.walking.server.listener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/*
* Walking Client listener Thread!
*/
public class WalkingCLT extends Thread {
private Socket client;
public WalkingCLT(Socket client){
super("Walking client listener thread!");
this.client = client;
}
#Override
public void run(){
System.out.println("HELLO?");
try {
System.out.println("User:" + client.getInetAddress() + "connected!");
PrintWriter out = new PrintWriter(client.getOutputStream(),true);
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out.println("HELLO?");
out.flush();
out.close();
in.close();
client.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I've put some println statments to see if it comes to that but I only see this:
Server stacktrace:
Created server socket
Client stacktrace:
Panel Created!
Your connected!
Hope you can help me.
Thanks!
You are only creating an instance of the SwingWorker task. You are missing a call to work.execute() or work.doInBackground() by some helper class. You need to look at the ExecutorService and how to use it to submit and execute SwingWorker tasks. There is also a small code snippet in the Future documentation.