I am currently developing a client and a server for a small game.
The client which connects to the server establishes the connection with this method:
// This method is called, passing on an ipv6 address and port number 6666
public void startConnection(String ip, int port) throws IOException {
try {
clientSocket = new Socket(ip, port);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//some other code handling responses
} catch (IOException e) {
LOG.debug("Error when initializing connection", e);
throw new IOException();
}
}
The Server I built accepts connections using this method:
public void start(int port) {
try {
serverSocket = new ServerSocket(port); //port = 6666
//This part is used to handle multiple connections at once
while (b){
try {
map.add(new EchoClientHandler(serverSocket.accept())); //EchoClientHandler is a class used to send and receive data instructions
x = map.size() - 1;
System.out.println("Establishing connection from port " + port);
map.get(x).start();
System.out.println("Connection established");
} catch (SocketTimeoutException e) {
}
}
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Both methods work fine and establish a stable connection between the client and the server, but when i try and establish a connection from different routers or general internet connections (like via cellular data) it doesn't work.
Is there a way to establish connections without both the client and the server having to connect from the same router?
Edit:
Here is the error i get from the client, the server doesn't show anything:
18:03:24.288 [AWT-EventQueue-0] DEBUG dorusblanken.werwolfclient.Client - Error when initializing connection
java.net.SocketException: Network is unreachable: connect
"Network is unreachable" means there is no way to get to the destination network from the current network.
You mentioned that you are trying to establish a connection via the Internet. For that to work, the destination host (your server) must be connected to the Internet, it must have a public IP address, and the clients need to use the public IP address when connecting.
That is the simplest configuration. Most companies don't actually put their servers directly on the Internet. Instead, the public IP frequently belongs to a CDN or DDoS mitigation layer, which forwards connections to a load balancer, and the load balancer forwards connections to servers.
Related
I would like to connect by TCP to a machine given its IP address and its port.
I decided to use the JAVA java.net.Socket class and its connect method as it seems to fit my need.
For testing purpose, as the machines I need to test are not yet available, I tried to connect a local machine on its standard port 80.
But I was very surprised to see that it succeeded with any IP address, even an unknown one: I cannot "ping" it, but the connect method gives me success...
Did I missed something in JAVA Socket understanding?
How is this behaviour possible?
Here is my code :
private void testSocketConnection() {
try (Socket socketToMachine = new Socket()) {
InetSocketAddress address = new InetSocketAddress(InetAddress.getByName("1.2.3.4"), 80);
socketToMachine.connect(address, 1000);
System.out.println("SUCCESS");
} catch (UnknownHostException uhe) {
System.out.println("UnknownHostException");
} catch (IOException ioe) {
System.out.println("IOException");
}
}
I'm writing a Java program and I often face the problem that antivirus software block internet connection when users download my application.
So, I found an interesting way how to check internet access if it's blocked by antivirus: I use sockets and try to connect to Google DNS via 53 port.
E.g. avast don't block this connection and I can understand - does user has a real internet connection or not.
public static boolean checkRealInternetConnection() {
return checkInternet("8.8.8.8", 53);
}
private static boolean checkInternet(String host, int port) {
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(host, port), 5000);
return true;
} catch (Exception e) {
return false;
}
}
So, my question: is this good solution?
P.S. If user has a real internet connection and doesn't have connection to my website via port 80 - I show a message that antivirus software can block connection.
I am trying to create a socket connection between a .Net server application and Java Client Application.
I am getting an error from the java client application:
Connection refused: connect
Notes:
Communicating with a .Net Client Application, works fine.
I have disables the windows firewall
Undoubtedly, I am running the server application in the background and then I am running the client application
Following are my server code (C#):
public class Server
{
public Server()
{
CreateListener();
}
public void CreateListener()
{
// Create an instance of the TcpListener class.
TcpListener tcpListener = null;
IPAddress ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
string output;
try
{
// Set the listener on the local IP address
// and specify the port.
tcpListener = new TcpListener(ipAddress, 13);
tcpListener.Start();
output = "Waiting for a connection...";
}
catch (Exception e)
{
output = "Error: " + e.ToString();
MessageBox.Show(output);
}
}
}
and client application code (Java):
public class smtpClient {
public void Send() {
Socket smtpSocket = null;
DataOutputStream os = null;
DataInputStream is = null;
try {
smtpSocket = new Socket("localhost", 13); // FAILURE
os = new DataOutputStream(smtpSocket.getOutputStream());
is = new DataInputStream(smtpSocket.getInputStream());
} catch (UnknownHostException e) {
System.err.println("Don't know about host: hostname");
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
It fails at the following line in the Java Client Application:
smtpSocket = new Socket("localhost", 13);
I can't tell what is the issue you are facing, but you need to start with a solid foundation to discover these issues.
As a rule of thumb, you should always write one piece (typically the server) first and verify connectivity (say using telnet) and then write the other piece (typically client) and verify its connectivity.
I always keep a Standard Client and Server handy to test whether its my code or its the environment/configuration.
Below is a sample code that works fine to test connectivity.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
class ClientServer {
static void Main() {
new Thread(() => { StartServer("localhost", 5013); }).Start();
Thread.Sleep(100);
Console.WriteLine("\nPress enter to start the client...");
Console.ReadLine();
StartClient("localhost", 5013);
}
public static void StartServer(string serverInterface, int port) {
try {
IPHostEntry hostInfo = Dns.GetHostEntry(serverInterface);
string hostName = hostInfo.HostName;
IPAddress ipAddress = hostInfo.AddressList[0];
var server = new TcpListener(ipAddress, port);
server.Start();
Console.WriteLine($"Waiting for a connection at {server.LocalEndpoint}");
Console.WriteLine("Press ctrl+c to exit server...");
while (true) {
TcpClient client = server.AcceptTcpClient();
Console.WriteLine($"Server says - Client connected: {client.Client.RemoteEndPoint}");
ThreadPool.QueueUserWorkItem((state) => {
using (var _client = (TcpClient)state)
using (NetworkStream stream = _client.GetStream()) {
string msg = stream.ReadAsciiData();
if (msg == "Hello!") {
stream.WriteAsciiData($"Time:{DateTime.Now: yyyy/MM/dd HH:mm zzz}. Server name is {hostName}");
}
}
}, client);
}
} catch (Exception e) {
Console.WriteLine(e);
}
}
public static void StartClient(string serverInterface, int port) {
Console.WriteLine("Client started...");
try {
using (var client = new TcpClient(serverInterface, port))
using (NetworkStream stream = client.GetStream()) {
Console.WriteLine("Client says - Hello!");
stream.Write(Encoding.ASCII.GetBytes("Hello!"));
string msg = stream.ReadAsciiData();
Console.WriteLine($"Client says - Message from server: Server#{client.Client.RemoteEndPoint}: {msg}");
}
} catch (Exception e) {
Console.WriteLine(e);
}
Console.WriteLine("Client exited");
}
}
static class Utils {
public static void WriteAsciiData(this NetworkStream stream, string data) {
stream.Write(Encoding.ASCII.GetBytes(data));
}
public static string ReadAsciiData(this NetworkStream stream) {
var buffer = new byte[1024];
int read = stream.Read(buffer, 0, buffer.Length);
return Encoding.ASCII.GetString(buffer, 0, read);
}
public static void Write(this NetworkStream stream, byte[] data) {
stream.Write(data, 0, data.Length);
}
}
Now to your specific problem,
The choice of port 13, is not ideal for testing. Usually all ports below 1024 are considered privileged. i.e. a firewall or antivirus might block your attempt to listen on that port
Remember that IPV6 addresses plays a role. Your machine might have that enabled or disabled based on your configuration. You want to make sure that if your server is listening on a IPv6 interface, then your client also connects on the same
Which brings us to another related point: Irrespective of you are using IPv6 interface or not, the client needs to connect to the same interface the server is listening on. This might seem obvious, but is often missed. A typical machine
has at-least 2 interfaces: One for localhost (127...* called loopback interface) and another non local (typically 10...* or 192...*, but not restricted to it). It can so happen (especially when you pick the first available interface to bind your server without knowing which one it is) that server might be listening on non loopback interface like say 192.168.1.10 interface and the client might be connecting to 127.0.0.1, and you can see why the client will get "connection refused" errors
The sample code above works and you can test your code with it. You can us telnet for a client or just my sample code. You can play around changing the serverInterface values to some surprising discoveries which are accentuated by
ipAddress = hostInfo.AddressList[0] line
Hope this helps you with your debugging
I'm trying to build a basic client-server application.
When I run both the server and the client on the same computer both manage to connect without a hitch but if I try to do so from different computers (desktop and laptop) the connection doesn't get though. The server isn't even aware that someone tried to connect to it while the client timeouts after a while. At first I assumed that it's a firewall problem but disabling the firewall completely on the server PC did not help. Tried changing ports and checked on multiple computers. Any ideas what could cause this?
I control both the server and the client and can change the code of both if necessary. The server always runs on the same PC and I'm connecting to it directly using hardcoded IP address.
This is the code of the client sending random int to the server.
public static void main(String[] args) {
Socket s = new Socket();
try {
s.connect(new InetSocketAddress("123.45.67.891", 8084), 5000);
s.getOutputStream().write(42);
s.close();
} catch (IOException e) {
e.printStackTrace();
return;
}
}
The server is slightly more complicated but considering the fact that they manage to connect while being run from the same PC I assume that the problem isn't with it.
edit: Server code (Thread per client. There shouldn't be too many of those)
public void run() {
try {
serverSocket = new ServerSocket(listenPort); //integer
} catch (IOException e) { ... }
while (shouldRun) {
try {
Socket clientSocket = serverSocket.accept(); // Blocked here while trying to connect from remote computer
//Never gets here
ConnectionHandler newConnection = connectionHandlerCreator.create(clientSocket);
connectionHandlers.add(newConnection);
newConnection.initialize();
new Thread(newConnection).start();
} catch (IOException e) { ... }
}
}
Initialize consists of the following (which latter used for I/O).
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
out = new PrintWriter(clientSocket.getOutputStream(), true);
The problem is probably on your server side though: you have to make it respond to all ip's not just local one, by using the constructor:
ServerSocket(int port)
it will default accepting connections on any addresses which is not the case if you specified an IP
I have a socket client (on android phone) and server (on PC) both on a wifi network and the server successfully reads data from the client.
However, when I turn off the wifi on the phone the server read just hangs, whereas I was hoping some error would be thrown.
I do have setSoTimeout set on the server, but the read is not timing out.
On the PC netstat still shows an established connection
netstat -na | grep 6668
TCP 192.168.43.202:6668 192.168.43.26:43076 ESTABLISHED
Is there a way to tell if the client host has disappeared, or getting the read to time out?
Here is the server read
if (ss.isConnected()) {
try {
readData();
} catch (java.net.SocketTimeoutException ex) {
logger.warning(ex.toString());
} catch (InterruptedIOException ex) {
logger.warning(ex.toString());
} catch (IOException ex) {
logger.log(Level.WARNING, "Data communication lost will close streams - IOEx - socket status {0}", ss.socketStatus());
closeStreams();
} catch (Exception ex) {
logger.log(Level.WARNING, "Data communication lost will close streams - Ex - socket status {0}", ss.socketStatus());
closeStreams();
}
}
Where readData is,
public void readData() throws IOException {
for (int i = 0; i < data.length; i++) {
data[i] = ss.readDouble();
}
}
ss.readDouble() is,
public double readDouble() throws IOException {
return in.readDouble();
}
And the server connection,
public void connect() throws IOException {
if (serverSocket == null || serverSocket.isClosed()) {
init();
}
logger.log(Level.INFO, "Wait on " + serverSocket.getLocalPort());
server = serverSocket.accept();
serverSocket.close();
logger.log(Level.INFO, "Connected to {0}", server.getRemoteSocketAddress());
out = new DataOutputStream(server.getOutputStream());
in = new DataInputStream(server.getInputStream());
}
Make a timeout, so let's say no data has been sent for 10 minutes, close it in 60 seconds!
Setting a timeout for socket operations
The answer for this question may help you.
This is nature of TCP connection, not java sockets per se. If the remote peer disconects with broken connection, how should your server know that the peer simply has no data to send?
Writting on closed socket will cause exception, read will simply block if client doesnt end tcp connection properly, for the reason above.
If you go through socket API, you will find option to set timeout ( before proceeding with blocking operation).
You could also consider TCP KEEP Alive, which is also exposed by the Socket API.
// Edit: additional information as per the OP comment
When your client connects to server, you create a client socket to communicate with the peer. Your server socket is the one at which you are listening for new client connections. It is the client socket at which you specify keep alive or read timeout because this is the socket from which you read/write.
// your server is actually reference to ClientSocket
server = serverSocket.accept();
// keep alive duh
server.setKeepAlive(true);
serverSocket.close();