Only local client can connect only to server.
Client side code:
public InetAddress ipAddress;
private DatagramSocket socket;
public Client()
{
try
{
this.socket = new DatagramSocket();
this.ipAddress = getIpAddress();
}
catch (SocketException e)
{
e.printStackTrace();
}
}
public void run()
{
while(true)
{
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, 1331);
try
{
socket.send(packet);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
private InetAddress getIpAddress()
{
String ipAddress;
try
{
URL url = new URL("http://checkip.amazonaws.com/");
BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
ipAddress = br.readLine();
} catch (IOException e)
{
e.printStackTrace();
ipAddress = "null";
}
try
{
return InetAddress.getByName(ipAddress);
}
catch (UnknownHostException e)
{
e.printStackTrace();
return null;
}
}
public static void main(String args[])
{
Client client = new Client();
client.start();
}
Server side code:
private DatagramSocket socket;
public Server()
{
try
{
this.socket = new DatagramSocket(null);
socket.bind(new InetSocketAddress(getIpAddress(), 1331));
System.out.println(socket.getInetAddress());
}
catch (SocketException e)
{
e.printStackTrace();
}
}
public void run()
{
while(true)
{
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
try
{
socket.receive(packet);
System.out.println("aa");
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
private InetAddress getIpAddress()
{
try
{
return InetAddress.getByName("0.0.0.0");
}
catch (UnknownHostException e)
{
e.printStackTrace();
return null;
}
}
public static void main(String args[])
{
Server server = new Server();
server.start();
}
I tried to off my firewall, off Windows Defender, add NAT to router.
Also i checked if port is foreign port in netstat.
The only way to work fine server is to change ipAddress of client to "localhost"
Then code is working fine.
Is there and method how can i add address to server and players can connect to server with only ip address?
In order to connect the server multiple other computers, you should set the clients IP address to the address of the server's computer.
How to know what's the IP address of the server computer?
In the computer where the server installed:
Windows: go to CMD and then type ipconfig you need the IPv4 address.
Mac: go to terminal and then type ifconfig you need inet address.
Related
I just got started with socket programming so in order to improve my understandings of it I wanna build a multi-client chat application.
They way I intend to do it is the following:
Once the application starts you have two choices: create server or join server.
If you chose to create a server a new thread will start and host the server, then another thread will start which is gonna create a new client and automatically connect to the server just build.
And here I've encountered the following problem.
Each client can send messages to the server, but in order to keep them synchronized for all clients I was thinking to redirect the retrieved messages from the server to all clients as shown in the following diagram.
The thing is that when I try to listen and send on both client and server I get this errors.
java.net.SocketException: Connection reset
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:186)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:140)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:200)
at java.base/java.io.DataInputStream.readUnsignedShort(DataInputStream.java:342)
at java.base/java.io.DataInputStream.readUTF(DataInputStream.java:594)
at java.base/java.io.DataInputStream.readUTF(DataInputStream.java:569)
at parctice.Server.lambda$main$0(Server.java:32)
at java.base/java.lang.Thread.run(Thread.java:835)
This is my server:
int port = 4444;
try {
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("server starts port = " + serverSocket.getLocalSocketAddress());
while(true){
Socket socket = serverSocket.accept();
System.out.println("accepts : " + socket.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
String[] message = {""};
new Thread(() -> {
try {
while(in.available() > 0){
System.out.println("SERVER > " + in.readUTF());
message[0] = in.readUTF();
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
System.err.println(message[0]);
try {
out.writeUTF(message[0] + "REDIRECTED MESSAGE");
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
and my client:
int portNumber = 4444;
System.out.println("CLIENT > Trying to connect to the server...");
try {
Socket socket = new Socket("localhost", portNumber);
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
new Thread(() -> {
try {
while(in.available() > 0){
System.out.println("SERVER > " + in.readUTF());
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
try {
out.writeUTF("test");
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
In the end I would like to ask you guys if you think that the logic that I try to use is the right one and if not please let me know what's wrong and also if possible could you explain me why I am not being able to listen and send on both, client and server? Because when I try to send data through client and retrieve it on the server it works just fine, but I would like to accomplish both ways communication.
I've found this solution which seems to work for this scenario
First time we create the server:
private List<ClientThread> clients; // or "protected static List<ClientThread> clients;"
public List<ClientThread> getClients(){
return clients;
}
private void startServer(){
clients = new ArrayList<ClientThread>();
try {
serverSocket = new ServerSocket(PORT);
System.out.println("SERVER ON");
System.out.println("SERVER > Waiting for connections...");
// ACCEPT ALL CONNECTIONS
while (true){
try {
Socket socket = serverSocket.accept();
System.out.println("SERVER > New connection: " + socket.getRemoteSocketAddress());
ClientThread client = new ClientThread(this, socket);
Thread thread = new Thread(client);
thread.start();
clients.add(client);
} catch (IOException e) {
e.printStackTrace();
System.out.println("SERVER > Accept failed");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
Then for each client we create a new thread
public class ClientThread implements Runnable {
private Socket socket;
private Server server;
private String clientName;
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}
public ClientThread(Server server, Socket socket) {
this.server = server;
this.socket = socket;
}
#Override
public void run() {
try {
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeUTF("HI FROM SERVER");
while (!socket.isClosed()) {
try {
if (in.available() > 0) {
String input = in.readUTF();
// UNCOMMENT TO READ ON SERVER
// System.out.println("SERVER > " + input);
for (ClientThread thatClient : server.getClients()){
DataOutputStream outputParticularClient = new DataOutputStream(thatClient.getSocket().getOutputStream());
outputParticularClient.writeUTF(input + " GOT FROM SERVER");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Client:
public void createClient(){
try {
socket = new Socket("localhost", portNumber);
// socket = new Socket(getHost(), portNumber);
DataInputStream in = new DataInputStream(socket.getInputStream());
new Thread(()->{
while(!socket.isClosed()){
try {
if (in.available() > 0){
String input = in.readUTF();
System.out.println(getUserName() + " > " + input);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}
I am able to connect my DatagramSocket server and client inside my local area network(LAN) but I am unable outside of it.
Here is my code:
GameServer class:
public class GameServer extends Thread {
private DatagramSocket socket;
public GameServer() {
try {
this.socket = new DatagramSocket(7081,InetAddress.getByName("0.0.0.0"));
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
while (true) {
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
try {
socket.receive(packet);
if(new String(packet.getData()).trim().equalsIgnoreCase("ping")){
sendData("pong".getBytes(),packet.getAddress(),packet.getPort());
}
System.out.println(new String(packet.getData()));
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void sendData(byte[] data, InetAddress ipAddress, int port) {
DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, port);
try {
this.socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
GameClient class:
public class GameClient extends Thread {
private InetAddress ipAddress;
private DatagramSocket socket;
public GameClient(String ipAddress) {
try {
this.socket = new DatagramSocket();
this.ipAddress = InetAddress.getByName(ipAddress);
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
public void run() {
while (true) {
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
try {
socket.receive(packet);
System.out.println(new String(packet.getData()));
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void sendData(byte[] data) {
DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, 7081);
try {
socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
RunClient class:
public class RunClient {
public static void main(String[] args) {
GameClient client = new GameClient("/*Here is my external ip address*/"); //If i am running this for LAN then 192.168.1.67 and localhost work
client.start();
client.sendData("ping".getBytes());
}
}
RunServer class:
public class RunServer {
public static void main(String[] args) {
GameServer server = new GameServer();
server.start();
}
}
Here are my port forwarding configurations:
Some additional information:
My local ip address is 192.168.1.67
The port I am using is 7081
When I check my ip and port at http://www.canyouseeme.org it gave me the following error:
Error: I could not see your service on "my external ip" on port (7081)
I don't see any problem in your code. That site (http://www.canyouseeme.org) must be trying with TCP instead of UDP.
Please add exception for the port 7081 into firewall, so that it allow incoming connections on port.
when you are trying in LAN the IP might be different, when you are trying outside, you have to try with the external ip, which should be configured to redirect the request to your localip.
Thanks,
Ankireddy Polu
I recently started making a 2D java game, and started making a tcp server 2 days ago, now that all my other issues are fixed, I would like to address the fact that the client can only connect to the server when it is on the same device and using the devices static ip, though it cannot connect using my wan ip address, I have port forwarded and I have checked on many port-checker websites and they all can see my server, my firewall is also disabled, yet the client can't see the server using the wan ip, I made a mine craft server on the same port (Minecraft servers are also tcp) and others were able to connect using my wan ip. When a client does try to connect using my wan ip, it gives a Connection Refused exception. What am i doing wrong?
Client (Can't connect to server over nat):
package com.diedericksclan.main.network;
import java.io.*;
import java.net.*;
import java.util.Enumeration;
public class ClientThread extends Thread {
private ClientHandler client;
private Socket socket;
private InetSocketAddress address;
private int megabyte = 1024 * 1024;
private DataInputStream in;
private DataOutputStream out;
public ClientThread(ClientHandler client, InetSocketAddress address) {
this.client = client;
this.address = address;
socket = new Socket();
try {
socket.setSendBufferSize(megabyte);
socket.setSendBufferSize(megabyte);
socket.setTcpNoDelay(true);
socket.setReuseAddress(true);
socket.bind(new InetSocketAddress(this.getIP(), 0));
System.out.println(socket.getLocalAddress().getHostAddress() + ":" + socket.getLocalPort() + " is a new client!");
socket.connect(address);
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private InetAddress getIP() throws SocketException {
Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
NetworkInterface ni;
while (nis.hasMoreElements()) {
ni = nis.nextElement();
if (!ni.isLoopback() && ni.isUp()) {
for (InterfaceAddress ia : ni.getInterfaceAddresses()) {
if (ia.getAddress().getAddress().length == 4) {
return ia.getAddress();
}
}
}
}
return null;
}
long starttime;
long endtime;
long overall;
public void run() {
byte[] data;
while(true) {
try {
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
data = new byte[in.readInt() - 4];
in.read(data);
client.parsePacket(data, socket.getInetAddress(), socket.getPort());
endtime = System.nanoTime();
overall = endtime - starttime;
//System.out.println("CLIENT >> SERVER >> CLIENT - Time was: " + overall + " nano seconds!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public synchronized void sendData(byte[] data) {
try {
try { socket.connect(address); } catch (IOException e) {}
out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
starttime = System.nanoTime();
out.writeInt(data.length + 4);
out.write(data);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public void serverShutdown() {
try {
this.socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Server (Can be seen by everything but client):
package com.diedericksclan.main.network;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import com.diedericksclan.main.network.handling.PlayerMP;
public class ServerThread extends Thread {
private ServerHandler server;
private ServerSocket dataSocket;
private Socket socket;
private InetSocketAddress address;
private int megabyte = 1024 * 1024;
private int dedicated = 1024;
public int RAM = megabyte * dedicated;
private ArrayList<Client> clients = new ArrayList<Client>();
public ServerThread(ServerHandler server, String serverIP, int ram, int backlog) throws Exception {
super(serverIP);
this.server = server;
this.dedicated = ram;
String ip = "localhost";
int port = 2048;
if(serverIP.contains(":")) {
ip = serverIP.split(":")[0];
port = Integer.parseInt(serverIP.split(":")[1]);
} else {
ip = serverIP;
port = 2048;
}
this.dataSocket = new ServerSocket();
this.dataSocket.setReuseAddress(true);
this.address = new InetSocketAddress(InetAddress.getByName(ip), port);
this.dataSocket.bind(address, 0);
}
public ServerThread(ServerHandler server, String ip) throws Exception {
this(server, ip, 1024, 0);
}
public void run() {
while(true) {
try {
socket = dataSocket.accept();
socket.setKeepAlive(true);
socket.setSendBufferSize(megabyte);
socket.setSendBufferSize(megabyte);
socket.setTcpNoDelay(true);
socket.setReuseAddress(true);
InetSocketAddress clientAddress = new InetSocketAddress(socket.getInetAddress(), socket.getPort());
System.out.println("Starting");
if(getClients().size() > 0) {
for(Client c : getClients()) {
if(clientAddress != c.socket.getLocalSocketAddress()) {
Client client = new Client(socket, clientAddress);
getClients().add(client);
client.start();
System.out.println("Added new client!");
break;
}
}
} else {
Client client = new Client(socket, clientAddress);
getClients().add(client);
client.start();
System.out.println("Added new client!");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public synchronized void sendData(byte[] data, InetAddress IPaddress, int port) {
if(this.getClient(new InetSocketAddress(IPaddress, port)) != null) {
this.getClient(new InetSocketAddress(IPaddress, port)).sendData(data);
}
}
public void serverShutdown() {
try {
this.dataSocket.close();
if(this.socket != null) this.socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public int getClientIndex(InetSocketAddress address) {
int index = 0;
for(Client c : getClients()) {
if(c.socket.getRemoteSocketAddress().equals(address)) {
break;
}
index++;
}
System.out.println("Getting client index...");
return index;
}
public synchronized ArrayList<Client> getClients() {
return this.clients;
}
private Client getClient(InetSocketAddress address) {
for(Client c : getClients()) {
if(c.socket.getRemoteSocketAddress().equals(address)) {
return c;
}
}
return null;
}
public class Client extends Thread {
DataInputStream in;
DataOutputStream out;
Socket socket;
public Client(Socket sock, InetSocketAddress IPaddress) {
try {
socket = sock;
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
while(true) {
try {
byte[] data = new byte[in.readInt() - 4];
in.read(data);
server.parsePacket(data, socket.getInetAddress(), socket.getPort());
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void sendData(byte[] data) {
try {
out.writeInt(data.length + 4);
out.write(data);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
I would really appreciate it if someone could help.
-Regards
user.....
Port forwarding does not work when both machines are on the same LAN. Here's why:
The client sends a packet to the server's WAN address. It goes to the router. (Because machines on a LAN use the router to reach any WAN address.)
The router port forwards the packet to the server's LAN address. The source IP address is not changed, it's still the client's LAN address. (That's what port forwarding does.)
The server accepts the TCP connection by sending packets to the address it saw as the source address of the packets it received -- the client's LAN address. And, of course it gives them the only source IP address it can, it's LAN address.
Packets sent from the server to the client's LAN address go directly to the client, the router has no opportunity to NAT them because they are sent to the client's LAN address. (Here's where things go awry. If the client had been on another network, the packets would have gone to the router, since that's how the server reaches other networks.)
The client receives packets from the server's LAN address, but it was expecting packets from the server's WAN address (since that's what it sent them to), so the connection cannot work.
If you want to connect to the server from other machines on the LAN you must either connect to the server's LAN address or use some form of dual-NAT such as hairpin NAT -- port forwarding won't work.
I'm having some problems receiving a String from a multicast.
It's the first time i'm using UDP multicast in Java.
I'm making a multiclient application over a LAN.
So i'm using Local Ip addresses.
I need the clients to find the server's IP address so they can send their data, requests, etc.
I let the server sent out a multicast with his own IP as a string every 5 seconds.
The clients should be able to receive it.
The problem is that they don't receive anything.
I'm testing with 2 devices so i don't need to use localhost.
Here's some of my code:
Server side:
public class MulticastIpSender extends Thread{
private String serverIp;
private int port;
private String multicastAddress;
private long WAITING_TIME = 5000; // 5 seconden
private DatagramSocket socket;
public MulticastIpSender(String serverIp, int port, String multicastAddress) throws SocketException {
super();
this.serverIp = serverIp;
this.port = port;
this.multicastAddress = multicastAddress;
socket = new DatagramSocket(port);
}
public void run() {
while(true){
try {
byte[] buf = new byte[256];
buf = serverIp.getBytes();
InetAddress group = InetAddress.getByName(multicastAddress);
DatagramPacket packet = new DatagramPacket(buf, buf.length, group, port);
socket.send(packet);
System.out.println("sent IP("+serverIp+") to group("+group+") on port "+port);
sleep(WAITING_TIME);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
I put this method in the main class:
private void sendIpAddressToListeners() {
try {
multicastIpSender = new MulticastIpSender(serverIp,PORT,"230.0.0.1");
multicastIpSender.run();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I get the serverIp like this:
String hostName = InetAddress.getLocalHost().getHostName();
InetAddress addrs[] = InetAddress.getAllByName(hostName);
if (!addr.isLoopbackAddress() && addr.isSiteLocalAddress()) {
myIp = addr.getHostAddress();
}
}
System.out.println ("\nIP = " + myIp);
return myIp;
on this device it gives me 192.168.1.2
CLIENT SIDE:
multicastSocket = new MulticastSocket(PORT);
InetAddress address = InetAddress.getByName(MULTICAST_ADDRESS);
multicastSocket.joinGroup(address);
DatagramPacket serverIpPacket;
byte[] buf = new byte[256];
serverIpPacket = new DatagramPacket(buf, buf.length);
while(receivedIp ==null){
multicastSocket.receive(serverIpPacket);
receivedIp = new String(serverIpPacket.getData(), 0, serverIpPacket.getLength());
System.out.println("received server ip: " + receivedIp);
}
!! PORT = 4445 in both server and client
I hope somebody can help me with this or can explain a better way to do this.
Send a normal DatagramPacket on broadcast address, the packet will be received by all hosts in local network (with same network configuration, important part is mask)
Use calculator to check your broadcast address, this one works good: http://www.subnet-calculator.com/
I'm developing some peer 2 peer app for my class and I was told for letting servers to discover each other they have to Multicast to their UDP port 1110 and listen to their UDP port 1110. I wrote the code like below for doing that. for testing I run 2 servers which both send and receive. but it seems nothing working. where do you think my problem is ?
I put 2 servers in 2 different folders. and I assigned to IP addresses to my NIC like this ifconfig eth0:3 192.168.0.11 netmask 255.255.255.0 up how should I tell each server about the new ip address?
BroadcastListner
class BroadcastListner implements Callable<Object> {
int PORT = 1110;
String IP = "255.255.255.255";
MulticastSocket socket ;
DatagramPacket packet;
InetAddress IPAD;
byte data[] = null ; //////////////change size
int numOfNodes;
BroadcastListner(String IP, int numOfNodes) {
try {
this.numOfNodes = numOfNodes;
this.IP = IP;
IPAD = InetAddress.getByName(IP);
socket = new MulticastSocket(PORT);
packet = new DatagramPacket(data,data.length);
} catch (Exception e) {
e.printStackTrace();
}
}
BroadcastListner(int numOfNodes) {
try{
this.numOfNodes = numOfNodes;
// this.IP = IP;
IPAD = InetAddress.getByName(IP);
socket = new MulticastSocket(PORT);
packet = new DatagramPacket(data,data.length);
} catch (Exception e) {
e.printStackTrace();
}
}
public String call() {
try{
socket.joinGroup(IPAD);
} catch (Exception e) {
e.printStackTrace();
return "";
}
while(true) {
try {
socket.receive(packet);
String str = new String(packet.getData());
System.out.println(" Time signal received from"+
packet.getAddress() + " Time is : " +str);
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
//socket.leaveGroup(IPAD);
//socket.close();
//return "";
}
}
BroadcastSender
class BroadcastSender implements Callable<Object> {
int PORT = 1110;
String IP = "255.255.255.255";
MulticastSocket socket;
DatagramPacket packet;
InetAddress IPAD;
byte[] data = "IAmAServer".getBytes();
//int numOfNodes;
String str = "IAmAServer";
BroadcastSender(String IP) {
try {
// this.numOfNodes = numOfNodes;
this.IP = IP;
IPAD = InetAddress.getByName(IP);
socket = new MulticastSocket();
} catch (Exception e) {
e.printStackTrace();
}
}
BroadcastSender() {
try{
// this.numOfNodes = numOfNodes;
// this.IP = IP;
IPAD = InetAddress.getByName(IP);
socket = new MulticastSocket();
} catch (Exception e) {
e.printStackTrace();
}
}
public String call() {
try {
socket.joinGroup(IPAD);
socket.setTimeToLive(10);
} catch (Exception e) {
e.printStackTrace();
return "";
}
while(true) {
try {
Thread.sleep(2000);
packet = new DatagramPacket (data,str.length(),IPAD,PORT);
socket.send(packet);
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
//return "";
}
}
You need to try the broadcast address of 192.168.0.255
An alternative is to use a multi-cast instead of broadcast address like 224.x.x.x which is not tied to a specific subnet.