For approximately one week I have been trying to create a simple chat-program to learn how to use datagrams and sockets, proceeding with success I'm now trying to make a more functional final version of it, to test what I have learned but I have run into a huge problem.
Sending packets between two local computers is easy as a breeze, but when it comes to sending them to other computers on the internet port-forwarding have been an issue. Looking into this I discovered UPnP and created an automatic UPnP port on the client using Cling to make it more user-friendly, server-side I always port-forward "manually", which means it can always receive under normal circumstances. but the client is facing a problem I didn't anticipate: they can't receive datagrams through the UPnP port. if you port forward them "manually" they can receive (they can always send though, and the server reads them loud and clear).
So my question is: can someone show me how to send/receive (don't know if it's the servers fault or the clients fault, problem lies either in how the server receives, or how the client sends) through UPnP ports? or am I using UPnP ports all wrong? my router, which is the test subject, have UPnp port enabled, and I have tested UDP and TCP ports along with datagramsockets and multicastsockets in every configuration I could think of.
TL:DR use UPnP or find other solution on how to send/receive datagrams through a router/modem.
I am extremely sorry if the code is a bit messy/buggy, not the full code, will post pastebin if asked.
Client:
public class Client {
public MulticastSocket rsocket = new MulticastSocket(25566);
public Client() throws IOException {
//creating UPnP port using Cling...
InetAddress inet = InetAddress.getLocalHost();
PortMapping desiredMapping = new PortMapping(25566,
inet.getHostAddress(), PortMapping.Protocol.UDP,
"Chatt program");
UpnpServiceImpl upnpService = new UpnpServiceImpl(
new PortMappingListener(desiredMapping));
upnpService.getControlPoint().search();
// loop the loop to get values from text fields used
// to receive messages from the server.
//point of interest, this is where the client should receive data, works on a normal
//portforward, doesn't on a UPnP port, no idea why.
byte[] info = new byte[256];
while (true) {
DatagramPacket receive = new DatagramPacket(info, info.length);
rsocket.receive(receive);
String rmessage = new String(receive.getData(), 0,receive.getLength());
System.Out.println(rmessage);
}
}
public static void main(String[] args) throws IOException {
new Client();
}
}
Server:
public class Server {
public MulticastSocket rsocket = new MulticastSocket(25565);
public Server() throws IOException {
String rmessage = new String("a message");
// send to clients, not working on UPnP port
send(rmessage, 25566);
}
public void send(String msg, int port) throws IOException {
byte[] message = msg.getBytes();
DatagramPacket gpacket = new DatagramPacket(message,message.length, address, 25566);
rsocket.send(gpacket);
}
public static void main(String[] args) throws IOException {
new Server();
}
}
Related
I am Running into a java.net.BindException: Address already in use (Bind failed) on a server-client socket app
I am trying to learn about Java sockets using a Youtube tutorial as a reference. My code seems to match everything in the video (except variables names) but, when trying to run the server and then the client sockets, I get:
Exception in thread "main" java.net.BindException: Address already in use (Bind failed)
I have tried even printing out the local port just to make sure I connect to the right available port but, nothing works. Is there any documentation I can look into to solve this problem? or any guidance?
Server.java
public class serverSocket {
public static void main(String args[]) throws IOException{
String message, serverResponse;
ServerSocket serverSocket = new ServerSocket(56789);
System.out.print(serverSocket.getLocalPort());
Socket acceptClientRequestSocket = serverSocket.accept();
Scanner serverScanner = new Scanner(acceptClientRequestSocket.getInputStream());
message = serverScanner.next();
System.out.println(message);
serverResponse = message.toUpperCase();
PrintStream newMessage = new PrintStream(acceptClientRequestSocket.getOutputStream());
newMessage.println(serverResponse);
}
}
Client.java
public class clientSocket {
public static void main(String args[]) throws UnknownHostException, IOException {
String message,outputMessage;
Scanner clientInput = new Scanner(System.in);
Socket clientSocket = new Socket("localhost",56789);
Scanner incomingStream = new Scanner(clientSocket.getInputStream());
System.out.println("Enter a message");
message = clientInput.next();
PrintStream printClientStream= new PrintStream(clientSocket.getOutputStream());
printClientStream.println(message);
outputMessage = incomingStream.next();
System.out.println(outputMessage);
}
}
Is there any documentation I can look into to solve this problem? or any guidance?
You have probably your previously exectued program still running. Check the running java processes. Kill the the previous one and try again.
If this wouldn't help try restarting your machine. If the problem persists after that then some service is already running on this port and is starting with the OS. In that case you can either change the port number in your app or disable that service.
I am creating a client-server communication application and would like the client to be able to detect and connect to the server automatically, given that they are on the same network.
Previously, my code was working across a Linux and Windows machine. I would broadcast a simple message and it could be read. I could also see the message while watching network traffic with Wireshark.
The approach I am taking is to
Get the broadcast address(es) on the network on the server.
For a given duration, broadcast a message (soon to be the server IP)
On the client side, wait until a message is received.
I am quite new to networking, so any obvious errors may not be immediately obvious to me.
Server broadcast code:
public class Broadcaster {
/* ... */
public void pulse() throws InterruptedException, IOException, SocketException {
Long elapsed = new Date().getTime();
Long timeout = elapsed + this.duration;
DatagramPacket packet = new DatagramPacket(this.message.getBytes(), this.message.length());
HashSet<InetAddress> channels = Broadcaster.getBroadcastChannels();
while(elapsed <= timeout) {
for(InetAddress channel : channels) {
DatagramSocket socket = new DatagramSocket(this.port);
socket.setBroadcast(true);
socket.connect(channel, this.port);
socket.send(packet);
System.out.println("Broadcast sent to " + channel.getHostAddress() + " (" + socket.getPort() + "): " + this.message);
socket.close();
}
Thread.sleep(this.frequency);
elapsed = new Date().getTime();
}
}
private static HashSet<InetAddress> getBroadcastChannels() throws SocketException {
/* Returns 192.168.0.255 */
}
public static void main(String[] args) {
Broadcaster heart = new Broadcaster("Hello from the Raspberry Pi!", 120000, 5000, 8027);
try {
heart.pulse();
} catch(SocketException e) {
/* ...etc... */
} finally {
System.out.println("Broadcasting completed.");
}
}
}
Client code:
public class BroadcastListener {
private int port;
private int length;
public BroadcastListener(int length, int port) {
this.port = port;
this.length = length;
}
public String getNext() throws IOException {
byte buffer[] = new byte[this.length];
DatagramSocket socket = new DatagramSocket(this.port);
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
System.out.println("Waiting on " + socket.getLocalSocketAddress());
socket.receive(packet);
socket.close();
return new String(buffer);
}
public static void main(String[] args) {
System.out.println("Listening for network broadcasts...");
BroadcastListener broadcast = new BroadcastListener(128, 8027);
try {
System.out.println("Received broadcast: " + broadcast.getNext());
} catch(IOException e) {
System.out.println("Could not receive broadcasts:");
System.out.println(e.getMessage());
}
}
}
The broadcast/netmask address as seen on both devices ifconfig output is netmask 255.255.255.0 broadcast 192.168.0.255
What confuses me the most is that Wireshark is still seeing the broadcast but when I run the client Java program, it just sits at socket.receive(packet);
Wireshark screenshot on Imgur
Both client & server are on port 8027. It is clear that the broadcaster is working, but the client broadcast listener is not. Does anyone have any idea what could be happening? Thanks!
As mentioned in the comments: Check your firewall :-)
Another thing i recognized was that if I sniff with wireshark, no other processes could receive that datagrams. After realizing that, I wrote a nodejs script, which exclusive=false by default but even that did not help. Maybe there is a kernel flag or something, that UDP datagrams cannot be 'consumed' by one process.
It looks like your server may be brodcasting on a different address than your client. Your client is not being assigned an InetAddress, try using this constructor for your socket in BroadcastListener
DatagramSocket socket = new DatagramSocket(new InetSocketAddress("192.168.0.255", this.port));
If that doesnt work you might try binding both your server and client to 127.0.0.1
You keep creating and destroying DatagramSockets. If the packet arrives at your host at a moment when you don't have a DatagramSocket bound to the port, it will be thrown away.
Create one DatagramSocket and leave it open for this life of this code.
Following is a thread which has a SOCKET listening at port 15445.
Whenever a Datagram packet is sent to it, it forwards back to the sender's address after adding a String(Reply from SERVER) in it. I want this code to run somewhere on the Internet, but I don't know where to start.
Is it possible? Can I run this code on a Tomcat server or do I need to do something different?
import java.io.*;
import java.net.*;
public class HelloWorld extends Thread {
protected DatagramSocket socket = null;
protected BufferedReader in = null;
public HelloWorld() throws IOException {
socket = new DatagramSocket(15445);
}
public void run() {
while (true) {
try {
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
InetAddress address = packet.getAddress();
int port = packet.getPort();
String s = "Reply from SERVER";
byte[] b= s.getBytes();
packet = new DatagramPacket(b, b.length, address, port);
socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
new HelloWorld().start();
}
}
No, Tomcat isn't a web server. It's a servlet/JSP engine that happens to have an HTTP server built in.
This looks like POJO with a main. Why can't you just run that as a service? Why do you think you need a web server?
Use Jetty (echo server is one of the tutorials afaik) and expose your port to the internet.
If your code works fine forward the necessary port through your router so it's reachable from the internet. If your looking for a hosted solution, vservers are a cheap way to start. http://www.superuser.com is the place to go for network configuration.
I wrote a simple client-server application. It works very well on my computer. but when my friend tries to connect my server he can't. I create the server on my computer with port 23. Here is the part of creating the server:
public Server(int port_number) throws IOException{
create_Server(port_number);
}
public static void main(String[] args) throws IOException {
int port_number=23;
new Server(port_number);
}
private void create_Server(int port_number) throws IOException{
ss = new ServerSocket(port_number);
System.out.println("Server is ready!");
while(true){
s=ss.accept();
System.out.println(s.getLocalAddress().getHostName() + " was connected!");
send_con_mes();
list.put(s,new DataOutputStream(s.getOutputStream()) );
new ServerThread(s,this).start();
}
}
and here is the client part ;
public void start_Chat() {
try {
Ip_addr = JOptionPane.showInputDialog("Enter the IP number of the server to connect : ");
s = new Socket(Ip_addr, 23);
Client_name = JOptionPane.showInputDialog("Enter your Nickname : ");
dis = new DataInputStream(s.getInputStream());
dos = new DataOutputStream(s.getOutputStream());
new Thread(Client.this).start();
well I can talk, send private messages etc. When I connect to server on my computer as clients, but the final problem is a client from another IP cannot get connected.
You have to configure your network to allow this port to be accessed. This means enabling firewall on you PC, and your routers etc. There is nothing you can do in Java to avoid having to get this right first.
EDIT: If the other machine is trying to connect to you via an Internet router they will have to use your public IP address rather than your internal PC address. If you don't know your public address you can use a site like http://whatismyipaddress.com/. Unless you have a static IP address it can change when you reconnect. (One reason to stay connected all the time)
I have a server-client pair and I want to create a listener on the client end for new server responses. I am not sure how to do this, right now I can only interact in a direct synchronous way.
Here is the server:
public class TestServer {
public static void main(String[] args) throws Exception {
TestServer myServer = new TestServer();
myServer.run();
}
private void run() throws Exception {
ServerSocket mySS = new ServerSocket(4443);
while(true) {
Socket SS_accept = mySS.accept();
BufferedReader myBR = new BufferedReader(new InputStreamReader(SS_accept.getInputStream()));
String temp = myBR.readLine();
System.out.println(temp);
if (temp!=null) {
PrintStream serverPS = new PrintStream(SS_accept.getOutputStream());
serverPS.println("Response received: " + temp);
}
}
}
}
As you can see, it sends a response when it gets one. However in general I won't be sure when other servers I use send responses, so I would like to create an asynchronous listener (or at least poll the server for a response every half-second or so).
Here is what I'm trying on the client end:
protected static String getServerResponse() throws IOException {
String temp;
try {
BufferedReader clientBR = new BufferedReader(new InputStreamReader(mySocket.getInputStream()));
temp = clientBR.readLine();
} catch (Exception e) {
temp = e.toString();
}
return temp;
}
And just for reference, yes, sending over data from client to server works fine (it System.out's the data correctly). However, when I call the above function to try and retrieve the server response, it just hangs my application, which is an Android application in case that's relevant.
What I want from a function is just the ability to ask the server if it has data for me and get it, and if not, then don't crash my damn app.
On the client side create a ConnectionManager class which will handle all the socket I/O. The ConnectionManager's connect() method will create and start a new thread which will listen for server responses. As soon as it will receive a response it will notify all the ConnectionManager's registered listeners. So in order to receive asynchronously the server responses you will have to register a listener in ConnectionManager using its register(SomeListener) method.
Also, you can have a look at JBoss Netty which is an asynchronous event-driven network application framework. It greatly simplifies and streamlines network programming such as TCP and UDP socket server.