Java Client/Server over IPv6 - java

I am trying to get some experience with Java network programming. So I made a simple text based game. This is how it looks on serverside:
try {
socket = new ServerSocket(PORT);
while(true) {
new ConnectedPlayer(socket.accept()).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
And this is the client:
System.setProperty("java.net.preferIPv6Addresses","true");
try {
InetAddress ad = InetAddress.getByName("2a02:8070:b84:6b00:a1d1:30d7:346b:7c14");
socket = new Socket(ad, 9001);
output = socket.getOutputStream();
out = new PrintWriter(output);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
The address above is the Ipv6 address of the machine running
the server, I got this one by a website which detects my IP addresses,
it is different from what I get when I use ipconfig though, tried it with both.
When I tested both on the same machine with localhost, it worked.
However, now I wanted to try it on two different machines, one in a different network. Problem is, my internet provider apparently restricts me to something called "dual stack lite" which means my Server could only be reached over Ipv6 if I understand it correctly. But then, no port forwarding is needed there. When I test it now, it won't connect and gives a timeout after some time. I disabled firewalls on both machines.

Related

How to create a socket that listens a localhost port in Android

Before explain my doubt I want to mension that there're three "actors" in this enviorement:
A desktop program executed in some server
A person who uses this program remotely through a computer
And an Android tablet application that is connected with the computer via USB
When the person clicks on a link bar in this program that he is using remotely there's a shell script that sends a string to the person's computer port(e.g 1100). The requirement is: After recive this string from the desktop send it to the tablet.
So, what is the best way to recive this string from the desktop to the tablet?
Now there's a java daemon that is running in the desktop computer who is listening the 1100 port. This java app is working as a intermidiate between the desktop computer and the tablet, but I think that maybe there's a way to delete this daemon and just using the tablet to recive the computer data creating a socket.
You can also implement Java Sockets in Android. Like wise on Desktop Sockets in Android listens on ports but this will be accessed locally as there is no such way to assign static usable IP to an Android device.
There is another solution which is socket.io
Socket.io is one of the best socket library i have ever used. Implement socket.io on Node.js server and on Android simply connect to Node.js server and you can send same string to all connected users whether it is a Desktop or Android.
private class ServerThread extends Thread {
#Override
public void run() {
try {
serverSocket = new ServerSocket(portNumber);
while (true) {
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
LOGGER.error("Error on accept!");
}
// new thread for a client
new EchoThread(clientSocket).start();
}
}catch (Exception e) {
e.printStackTrace();
}
finally {
if (serverSocket != null) {
try {
serverSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
public class EchoThread extends Thread {
protected Socket clientSocket;
BufferedReader br = null;
public EchoThread(Socket clientSocket) {
this.clientSocket = clientSocket;
}
public void run() {
try {
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (IOException e) {
...
}
isConnected = true;
while (isConnected) {
try {
receivedMessage = br.readLine();
if (!Strings.isNullOrEmpty(receivedMessage)) {
....
}
else {
//sleep 0,1s
//TODO (ver): Thread.sleep(100);
}
} catch (Exception e) {
if (e instanceof IOException) {
}
else if (e instanceof JsonSyntaxException){
}
else {
try {
Thread.sleep(2000);
} catch (InterruptedException inte) {
inte.printStackTrace();
}
}
}
if (//yourmessagecondition){
isConnected = false;
}
}
if (!isConnected){
try {
br.close();
clientSocket.close();
}catch (IOException ioe){
ioe.printStackTrace();
}
}
}
}
Hope this helps, it is working here... You probably find easier/simple examples on the Internet.
PS: If you are using a USB cable to communicate with the computer app, you can use the "adb forward" command, just google for some examples and accept this answer if it helped ;)

TCP Hole Punching and setReuseAddress() on Linux

I am working on a Java client/server application that involves P2P communication over TCP. I'm trying to implement TCP Hole Punching as described here: http://www.brynosaurus.com/pub/net/p2pnat/#sec-tcp. This requires simultaneously listening on and attempting to establish an outgoing connection using the same local TCP port. Apparently, this should work if the SO_REUSEADDR socket option is used, which I am setting via the setReuseAddress() method in Java. However, this is not working as I expected. Here is some test code:
import java.io.IOException;
import java.net.*;
public class Test {
public static void main(String args[]) {
new Thread() {
public void run() {
try {
ServerSocket ss = new ServerSocket();
ss.setReuseAddress(true);
ss.bind(new InetSocketAddress(7077));
ss.accept();
} catch (Exception e) {
System.out.println("ServerSocket exception: " + e.getMessage());
}
}
}.start();
Socket s;
while (true) {
s = new Socket();
try {
s.setReuseAddress(true);
s.bind(new InetSocketAddress(7077));
s.connect(new InetSocketAddress("192.168.0.103", 7077));
break;
} catch (Exception e) {
System.out.println("Socket exception: " + e.getMessage());
try { s.close(); } catch (IOException e1) { }
try { Thread.sleep(1000); } catch (InterruptedException e1) { }
}
}
}
}
This works as expected in Windows 7: the ServerSocket listens on port 7077 in its own thread and the Socket repeatedly attempts to connect to 192.168.0.103:7077. However, under Linux (Ubuntu) only the first Socket connection attempt works, and subsequent attempts get the "Address already in use" BindException. Shouldn't I be able to establish an outgoing connection from a TCP source port that I'm also listening on simultaneously, and to reuse the local port number immediately after closing the socket, since I have the SO_REUSEADDR option enabled?
In Linux, both sockets need to set SO_REUSEADDR socket option. Thus, if we want two sockets, sock1 and sock2 to be bound ot the same port, then s2 would be able to reuse the port/address only if both sock1 and sock2 set SO_REUSEADDR.
You are never closing your client socket, unless there is an exception, making the point of SO_REUSEADDR a no-op.
....
s = new Socket();
try {
// ...
} catch (Exception e) {
System.out.println("Socket exception: " + e.getMessage());
// remove try block from here
try { Thread.sleep(1000); } catch (InterruptedException e1) { }
} finally {
try { s.close(); } catch (IOException e1) { }
}
....
In the above, I moved the closing of the socket to a newly created finally block so it is always executed, even if you break out the global while loop.
Since the socket is now closed under all conditions, the SO_REUSEADDR will use correctly now.

can't connect Socket when not in same IP range. (subnet)

When running a ServerSocket on a machine A with ip 145.74.217.109
And then trying to connect to machine A using machine B with ip 145.74.219.103 I am unable to connect.
But when using machine C with ip 145.74.217.180 it works.
Iam not sure if this is solvable in code or its just network settings. If It is network issues is there another way to go around this problem or would I need to go away from sockets to ...?
Machine A:
public void run() {
try {
sock = new ServerSocket(Constants.PORT);
for (;;) {
Socket newsock = sock.accept();
System.out.println("Accepting new player: ");
new PaintballPlayer(newsock);
}
} catch (Exception e) {
System.out.println("IO error " + e);
}
System.out.println("End!");
try {
sock.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Machine B, C :
socket = new Socket(ip, Constants.PORT);
if you look at the IP us server has IP 145.74.217.109 IP with 145.74.217.180 are able to connect while 145.74.219.103 is not being able to connect it means subnet 145.74.219.X has no access to 145.74.217.X that is why it is not being able to connect. It is network setting ask you network administrator for that. Make your both machine have same subnet mask

Testing Socket Program

So I wrote a simple Socket program that send message from Client to Server program and wanted to know what is the proper procedure to go about testing this? Both my Client and Server machines are running on Ubuntu 12.04 and I'm remote connecting to both of them.
For my Client code when I instantiate the client socket (testSocket) do I use its IP Address and Port number or Servers IP Address and Port number?
Here is the Code for Client:
public static void main(String[] args) throws UnknownHostException, IOException
{
Socket testSocket = null;
DataOutputStream os = null;
DataInputStream is = null;
try
{
testSocket = new Socket("192.168.0.104", 5932);
os = new DataOutputStream(testSocket.getOutputStream());
is = new DataInputStream(testSocket.getInputStream());
}
catch (UnknownHostException e)
{
System.err.println("Couldn't find Host");
}
catch (IOException e)
{
System.err.println("Couldn't get I/O connection");
}
if (testSocket != null && os != null && is != null)
{
try
{
os.writeBytes("Hello Server!\n");
os.close();
is.close();
testSocket.close();
}
catch (UnknownHostException e)
{
System.err.println("Host not found");
}
catch (IOException e)
{
System.err.println("I/O Error");
}
}
}
Here is the code for Server:
public static void main(String[] args)
{
String line = new String() ;
try
{
ServerSocket echoServer = new ServerSocket(5932);
Socket clientSocket = echoServer.accept();
DataInputStream is = new DataInputStream(clientSocket.getInputStream());
PrintStream os = new PrintStream(clientSocket.getOutputStream());
while (true)
{
line = is.readLine();
os.println(line);
}
}
catch (IOException e)
{
System.out.println(e.getMessage());
}
}
I'm new to Sockets and not sure what I'm supposed be seeing. I compiled both programs in terminal fine but not sure which one should I be running first or do they need to be started simultaneously?
Thanks
Your server is running in a infinite loop. Avoid that.
You have to restart your computer.
while (true)
{
line = is.readLine();
os.println(line);
}
try
while (!line.equals("Hello Server!"))
{
line = is.readLine();
os.println(line);
}
Run the server first. echoServer.accept(); waits for a connection. When it gets the first connection,
http://docs.oracle.com/javase/tutorial/networking/sockets/ this is a short java tutorial on how to work with sockets and also you can learn how to make a server that would accept multiple connections at a time. This tutorial explains you always need to start the server first, which is only logical. You should use threads to manage connections and then close them so that you use resources efficiently

WiFi network programming in android

i want to program a server/client app in android.
i have one server class on my pc and client on my android phone.
all permissions are ok.
Here is client:
try {
mysocket = new Socket("My PC IP Address", 4444);
} catch (UnknownHostException e) {...
} catch (IOException e) {...
}
here is server:
try {
myServerSocket = new ServerSocket(4444);
} catch (IOException e) {...
}
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
System.out.println("Connection Established.");
} catch (IOException e) {
}
I uses "Connectify" program on my pc to have an (virtual)access point such that my phone connect to that.
But when I try to connect to server in my android app, it hangs and then throws Timed-out exception.
This code doesn't look bad.
Are you certain Connectify is working well?
You shoud try running both the server and the client you have built on your PC, using two different processes (as an example the server as a standalone and the client in the Android Emulator).
If it works properly from localhost to localhost:4444, the the connection is the cause of the problem, not your code. And otherwise, you will easily find the bug in your code.

Categories