Well, here's my code:
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.ServerSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class TcpServerEcho {
public static void main(String argv[]) {
int port = Integer.parseInt(argv[0]);
ServerSocket server_socket = null;
try {
InetAddress thisIp = InetAddress.getByName("kiravaio.homepc.it");
System.out.println(thisIp.getHostAddress());
//or
//server_socket = new ServerSocket(port, 10, InetAddress.getByName("79.47.49.68"));
server_socket = new ServerSocket(port, 10, thisIp);
}
catch (Exception e) {
System.err.println("Impossible to create socket server!");
System.out.flush();
System.exit(1);
}
System.out.printf("Server active on port: %d and on address %s\n", port, server_socket.getInetAddress());
Socket client_socket = null;
boolean exec = true;
while(exec) {
try {
client_socket = server_socket.accept();
InputStream is = client_socket.getInputStream();
OutputStream os = client_socket.getOutputStream();
boolean stop = false;
System.out.println("Received: ");
while(!stop) {
int b = is.read();
System.out.print((char)b);
if(b == -1) {stop = true;}
else {os.write( (byte)b );}
}
}
catch (IOException ioe) {
System.err.println("Error I/O!");
} finally {
try {
client_socket.close();
}
catch (IOException ioe) {}
}
System.out.println("");
}
try {
/* Never executed */
server_socket.close();
} catch (IOException ioe) {}
}
}
There's no way for me to create a socket on my public ip.
I have a domain
kiravaio.homepc.it
always updated everytime my ip public changes.
So as first, I get my ip address with
InetAddress thisIp = InetAddress.getByName("kiravaio.homepc.it");
then I create the socket:
server_socket = new ServerSocket(port, 10, thisIp);
But it always fails and I don't know why,
Only creating a socket on 127.0.0.1 works!
:(
Looking up homepc.it reveals this is a dyndns service domain name. That domain name is resolving to the IP of your router not your PC.
Your PC will have a private network IP address (e.g. 192.168.1.x) assigned to it by your router (that IP is being used by your PC to talk to your router which is performing NAT (Network Address Translation)) .
You have to bind to that address (or simply use the constructor for ServerSocket that only takes a port; this will bind to 0.0.0.0 (INADDR_ANY) and listen on all interfaces), and configure your router to forward the port you have chosen to that IP address.
(If you don't know how to do that, you should consult your router's manual or perhaps post a question to https://superuser.com/)
I strongly believe that for ServerSocket, you don't need to specify which ip address is going to be used, just do new ServerSocket(port) and the client should be able to connect via your dynamic domain.
Related
Edited after comment on proper use of SO_REUSEADDR
I want to use same port for both inbound and outbound connections in java
The purpose is to make a node in distributed environment. But in Tcp I need to use two different ports for accepting and initiating connections.
// accept incoming connection on one port
ServerSocket.accept()
// connect to remote, the port used will be different from the one used for accepting
Socket.connect()
Now the problem is:
A starts listening on port a. B on b and C on c.
when A connects B (Using Socket.connect()), A & B will keep the socket open for future message passing.
B still doesn't know the port A is listening on because the the port from which b received the connection is different from a.
when C connects B, B gives the socket address of A to C, But that port is a bound by a Socket() instance which doesn't have a accept() method
Of course, A can inform B about the port it is listening, but isn't there a direct way?
How can I make this test to pass?
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class DualSocketTest {
ExecutorService service= Executors.newFixedThreadPool(10);
int echoServerport=8080;
int localServerport=8090;
#Test
public void testConnectivity() throws IOException {
// create a echo server on port 8080
startEcho();
// create a local Server instance
ServerSocket localServer=new ServerSocket();
// set the reuseAddress to true
localServer.setReuseAddress(true);
// bind the serverSocket
localServer.bind(new InetSocketAddress(localServerport));
// create a socket to connect the echo server using the same port used by localServer
Socket socket = new Socket();
socket.setReuseAddress(true);
// but this will throw SocketBindException
socket.bind(new InetSocketAddress(localServerport));
socket.connect(new InetSocketAddress(echoServerport));
// write hello
socket.getOutputStream().write("Hello !".getBytes());
byte[] result=new byte[100];
// receive hello
String ans=new String(result,0,socket.getInputStream().read(result));
System.out.println("Server replied with : "+ans);
// what was written and what was received must be same.
assert(ans.equals("Hello !"));
}
// start a echo server listening on the specified port
private void startEcho() throws IOException {
ServerSocket echoServer=new ServerSocket(echoServerport);
service.submit(()->{
try {
while(!echoServer.isClosed()) {
Socket socket = echoServer.accept();
System.out.println("connected with :" + socket.getInetAddress().toString() + ":" + socket.getPort());
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
service.submit(() -> {
while (socket.isConnected()) {
try {
outputStream.write(inputStream.read());
} catch (IOException e) {
break;
}
}
System.out.println("The Client has closed connection.");
});
}
} catch (IOException e) {
e.printStackTrace();
}
});
Thread.yield();
}
// Write something to the socket.
}
There is no such problem in when I previously used udp. The same socket supports receive() and send() method. For udp, sharing address is easy.
when A connects B, B would save the socketAddress of A,
When C connects B, B would send the address of A to C and C would connect to A
Edit: WON'T WORK IN JAVA
SO_REUSEADDR option shall be set on a socket before binding. I initially did my tests in Python (no access to a Java environment) and following script worked without errors on a Windows 10 system:
import socket
serv = socket.socket() # set a listening socket
serv.bind(('0.0.0.0',8080))
serv.listen(5)
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('0.0.0.0',8080))
s.connect(('127.0.0.1', 8090))
with another process listening on port 8090
Unfortunately, in Java setReuseAddr javadoc says explicitely (emphasize mine):
Enabling SO_REUSEADDR prior to binding the socket using bind(SocketAddress) allows the socket to be bound even though a previous connection is in a timeout state.
For reasons I cannot guess, Java is more restrictive here. What looks even more weird, is that according to this other question it used to be allowed on older JRE versions (up to JRE 7U5)
Original (and wrong) post follows:
The trick is to set the SO_REUSEADDR option before binding. That means that you will need to use a parameterless constructor for both ServerSocket et Socket. More or less:
ServerSocket localServer = new ServerSocket();
localServer.setReuseAddress(true);
localServer.bind(InetSocketAddress(localServerport));
... // Ok listening...
Socket socket = new Socket();
socket.setReuseAddress(true);
socket.bind(InetSocketAddress(localServerport));
socket.connect(...);
That way you can connect from your local listening port so that the peer will know how to reconnect after the connection will be closed.
Beware: untested...
I've fixed your test - hope that it's the way you wanted it to be. Take a look at the code here:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.Test;
public class DualSocketTest {
ExecutorService service = Executors.newFixedThreadPool(10);
int echoServerport = 8080;
int localServerport = 8080;
#Test
public void testConnectivity() throws IOException {
// create a echo server on port 8080
startEcho();
// create a socket to connect the echo server using the same port used by localServer
Socket socket = new Socket();
// but this will throw SocketBindException
socket.connect(new InetSocketAddress(echoServerport));
// write hello
socket.getOutputStream().write("Hello !".getBytes());
socket.getOutputStream().flush();
byte[] result = new byte[100];
// receive hello
String ans = new String(result, 0, socket.getInputStream().read(result));
System.out.println("Server replied with : " + ans);
// what was written and what was received must be same.
assert (ans.equals("Hello !"));
}
// start a echo server listening on the specified port
private void startEcho() throws IOException {
ServerSocket echoServer = new ServerSocket(echoServerport);
service.submit(() -> {
try {
while (!echoServer.isClosed()) {
Socket socket = echoServer.accept();
System.out.println("connected with :" + socket.getInetAddress().toString() + ":" + socket.getPort());
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
service.submit(() -> {
while (socket.isConnected()) {
try {
byte[] buffer = new byte[1024];
int read = -1;
while ((read = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, read);
}
} catch (IOException e) {
break;
}
}
System.out.println("The Client has closed connection.");
});
}
} catch (IOException e) {
e.printStackTrace();
}
});
Thread.yield();
}
// Write something to the socket.
}
I came across a relatively simple java code while trying to design a Tcp PortScanner. The following code checks for the listening ports available on the local machine.
I wonder what kind of scan it uses to check its status, i mean is it using Tcp Syn scan , or Tcp connect scan or anything other than this. I'm grateful for your response.
import java.net.*;
import java.net.InetAddress;
import java.net.Socket;
class PortScanner {
public static void main(String []args) {
for (int port = 1; port <= 65535; port++) {
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress("localhost", port), 1000);
socket.close();
System.out.println("Port " + port + " is open");
} catch (Exception ex) {
}
}
}
}
First off, networking is not my strongest subject. So sorry if this question is ridiculous, or if I'm missing some major information. I'd be happy to provide any needed.
I am trying spoof a server program. The program I am trying to pretend to be basically creates a local server, then allows client versions of the same program to connect (provided they are on the same computer).
Using netstat -a -b -n I was able to figure out that the server was binding itself to 0.0.0.0:53640. The other information given was:
Proto: UDP
Local Address: 0.0.0.0:56426
Foreign Address: * : * (Without spaces, stackoverflow doesn't seem to like this when it doesn't have them)
State: (Was blank)
The closest I was able to come was
Proto: TCP
Local Address: 0.0.0.0:56426
Foreign Address: 0.0.0.0:0
State: LISTENING
The code that I am using is:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class Main2
{
public static void main(String args[])
{
String ip = "0.0.0.0";
int port = 53640;
try
{
InetAddress address = InetAddress.getByName(ip);
ServerSocket server = new ServerSocket(port, 5, address);
System.out.println("Waiting for connection...");
Socket socket = server.accept();
System.out.println("Got connection!");
doSocket(socket);
server.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static void doSocket(Socket socket)
{
try
{
System.out.println("Connection from: " + socket.getInetAddress());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream());
int b;
char c;
while ((b = in.read()) != -1)
{
c = (char) b;
System.out.print(c);
}
in.close();
out.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
ServerSocket.accept seems to never stop yielding, as "Got connection!" is never printed to the output.
All help is very welcome. Thanks in advance! And sorry if I've done something horribly wrong with this post, its my first one.
UDP is connection-less, and 'ServerSocket' is connection-oriented and TCP-only. Have a look at the Oracle docs on datagrams (UDP).
UDP ports and TCP ports are in different namespaces; you can't get mixups from one to the other.
In java it is possible to create a socket server and a socket client, is it possible to have an instance of the socket server running and a socket/server client that is receiving data from the socket server on the same machine?
e.g the socket server runs on port 60010
and the socket client is running on the same machine connecting to that port through a socket or will I need to by a new machine and add it to my network? If it has a unique IP Address and port number running on the TCP/IP layer.
Here's a simple runnable example to get you started. It starts two threads, one with a ServerSocket and one which makes a Socket connection. One continuously sends strings and the other prints them.
You should simply be able to run this class as-is.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
public class SocketTest {
public static void main(String[] args) throws IOException {
startServer();
startSender();
}
public static void startSender() {
(new Thread() {
#Override
public void run() {
try {
Socket s = new Socket("localhost", 60010);
BufferedWriter out = new BufferedWriter(
new OutputStreamWriter(s.getOutputStream()));
while (true) {
out.write("Hello World!");
out.newLine();
out.flush();
Thread.sleep(200);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
public static void startServer() {
(new Thread() {
#Override
public void run() {
ServerSocket ss;
try {
ss = new ServerSocket(60010);
Socket s = ss.accept();
BufferedReader in = new BufferedReader(
new InputStreamReader(s.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
Yes, you can have the following on the same machine:
ServerSocket server = new ServerSocket(60010);
Socket client = server.accept();
Somewhere else:
Socket socket = new Socket("localhost", 60010);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println("Hello server");
Yes, you can run a client and server on the same machine. I do it all the time for development. If you are having troubles though, some routers have problems forwarding packets back to themselves. Try using localhost instead of your external IP for development.
Yes it is completely possible. Every OS has a loopback interface. You can have multiple clients connect to one server on your computer. This kind of communication takes place over the loopback interface.
import java.net.*;
import java.io.IOException;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class PortScanner {
public static void main(String[] args) {
InetAddress ia=null;
String host=null;
try {
host=JOptionPane.showInputDialog("Enter the Host name to scan:\n example: example.com");
if(host!=null){
ia = InetAddress.getByName(host);
scan(ia); }
}
catch (UnknownHostException e) {
System.err.println(e );
}
System.out.println("Bye from NFS");
//System.exit(0);
}
public static void scan(final InetAddress remote) {
//variables for menu bar
int port=0;
String hostname = remote.getHostName();
for ( port = 70; port < 65536; port++) {
try {
Socket s = new Socket(remote,port);
System.out.println("Server is listening on port " + port+ " of " + hostname);
s.close();
break;
}
catch (IOException ex) {
// The remote host is not listening on this port
System.out.println("Server is not listening on port " + port+ " of " + hostname);
}
}//for ends
}
}
please help me.
I am not sure if this will speed things up, but since each socket your making is independent of the next socket, have you tried making more threads so that you can create new sockets when older sockets are waiting for their handshake to complete.
Instead of using the line
Socket s = new Socket(remote,port);
You should use
Socket s = new Socket();
int timeout = 100; // milliseconds
s.connect( new InetSocketAddress( remote, port ), timeout );
This way you won't have to wait for the default TCP timeout to see that this port is blocked by a firewall without any response.