I'm trying to make a chat program where the client and the server can chat with each other on different networks (not localhost) I'm currently faced with a problem that i don't know how to solve.
For some reason, the client and the server can't connect to each other, when i write a message to the server with the client, nothing pops up on the server. The tests were run on two different computers, on different networks (Mobile data and Ethernet)
I've used the public ip from my ethernet in the code, and portforwarded it with the matching port number in the code. The server is running on the portforwarded network.
This is my code:
CLIENT:
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class ChatClient {
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
DatagramSocket client = new DatagramSocket(7000);
byte[] receivedData = new byte[1024];
byte[] sentData;
InetAddress address = InetAddress.getByName(" PUBLIC IP IS HERE, won't show it for obvious reasons ");
while (true) {
String message = scanner.nextLine();
sentData = message.getBytes();
DatagramPacket dp1 = new DatagramPacket(sentData, sentData.length, address, 7000);
client.send(dp1);
DatagramPacket dp4 = new DatagramPacket(receivedData, receivedData.length);
client.receive(dp4);
String receivedMessage = new String(dp4.getData());
System.out.println(receivedMessage);
}
}
}
SERVER:
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class ChatServer {
public static void main(String[] args) throws IOException {
DatagramSocket server = new DatagramSocket();
Scanner scanner = new Scanner(System.in);
byte[] receivedData = new byte[1024];
byte[] sentData;
while (true) {
DatagramPacket dp2 = new DatagramPacket(receivedData, receivedData.length);
server.receive(dp2);
String storedData = new String(dp2.getData());
System.out.println(storedData);
InetAddress getIP = dp2.getAddress();
int port = dp2.getPort();
String sentMessage = scanner.nextLine();
sentData = sentMessage.getBytes();
DatagramPacket dp3 = new DatagramPacket(sentData, sentData.length, getIP, port);
server.send(dp3);
}
}
}
The code worked when altered to localhost only.
Does anyone know what i'm doing wrong? Any replies are greatly appreciated.
Assuming the client connects to the server, the server needs to specify the port to listen and the client needs to specify IP and port of the server.
Client:
InetAddress address = InetAddress.getByName(" PUBLIC IP IS HERE");
DatagramSocket client = new DatagramSocket();
//...
DatagramPacket dp1 = new DatagramPacket(sentData, sentData.length, address, 7000);//the port should be the publicly exposed port
client.send(dp1);
This connects to the server with specified IP and port.
Server:
DatagramSocket server = new DatagramSocket(7000);//port to forward
This means that the server listens on port 7000 so it is available under that port.
Aside from that, make sure the port forwarding works correctly. If you use UDP, you also need to configure it for TCP.
Also note that UDP does neither confirm nor validate packages. If you want to have those features, you will need to either use TCP or implement those features by yourself.
Related
We have code using UDP socket for communication. In this code, application is sending a packet to a given server (identified by given hostname and port). This code is an extracted out from a large code base.
class Test {
private static int UDP_PORT_NUMBER=15000;
public static void main(String args[]) {
String host = “192.168.2.10”;
byte[] bytes = {(byte)0xd1, 0x35, (byte)0x39, (byte)0xea, (byte)0xa2, (byte)0xd8};
DatagramSocket datagramSocket = new DatagramSocket();
final InetAddress inetAddress = InetAddress.getByName(host);
final DatagramPacket sendPacket = new DatagramPacket(bytes, bytes.length,
inetAddress, UDP_PORT_NUMBER);
datagramSocket.send(sendPacket);
}
}
However, I am getting following exception in our case while calling send on datagram socket:
java.io.IOException: Network is unreachable
at java.net.PlainDatagramSocketImpl.send(Native Method) ~[?:1.8.0_91]
at java.net.DatagramSocket.send(DatagramSocket.java:693) ~[?:1.8.0_91]
What is the meaning of network unreachable in UDP and how does it get detected for UDP which is connectionless? What are cases where I can get network unreachable IOException in UDP socket?
The network unreachable message is an ICMP message. When a host tries to reach another host on a different network, it sends the layer-3 packet to its configured gateway. If the gateway ( or any router in the path) doesn't know how to reach the other network, it will generate an ICMP message and send it back to the host.
I am trying to connect two Android devices to a c#-server and I always get a connection timeout.
The java-code is simple:
Socket socket = new Socket(mAddress, PORT);
If I start a java-server on the pc then the connection is successful. So its not a network/firewall problem.
But my c#-server just won't accept any connections, code:
private TcpListener serverSocket;
private TcpClient clientSocket1;
private TcpClient clientSocket2;
private void Form1_Load(object sender, EventArgs e)
{
serverSocket = new TcpListener(IPAddress.Any, port);
clientSocket1 = default(TcpClient);
clientSocket2 = default(TcpClient);
serverSocket.Start();
clientListenerThread = new Thread(wait4Clients);
clientListenerThread.Start();
}
private void wait4Clients()
{
logToConsole("Clientlistener started");
clientSocket1 = serverSocket.AcceptTcpClient();
logToConsole("Client No 1 started!");
clientSocket2 = serverSocket.AcceptTcpClient();
logToConsole("Client No 2 started!");
}
I also tried System.Net.Sockets.Socket instead of System.Net.Sockets.TcpClient, didnt worked either.
Thanks a lot
EDIT: Seems the code is perfectly fine. If I run the exe and not debug mode via Visual Studio, everything works. So the debug mode somehow prevents the server socket from working correctly. Any ideas why this happens?
// TCP Server C#, look at [msdn][1]
try
{
// Set the TcpListener on port 8080 of Any IP Address.
TcpListener server = new TcpListener(IPAddress.Any, 8080);
// Start listening for client requests.
server.Start();
// Buffer for reading data
Byte[] bytes = new Byte[1024];
String data = null;
// Enter the listening loop.
while(true) {
Console.Write("Waiting for a connection... ");
// Perform a blocking call to accept requests.
// You could also user server.AcceptSocket() here.
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
// Get a stream object for reading and writing
data = null;
NetworkStream stream = client.GetStream();
int i;
// Loop to receive all the data sent by the client.
while((i = stream.Read(bytes, 0, bytes.Length))!=0)
{
// Translate data bytes to a ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);
// Process the data sent by the client.
data = data.ToUpper();
byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);
// Send back a response.
stream.Write(msg, 0, msg.Length);
Console.WriteLine("Sent: {0}", data);
}
}
I have the code below which creates a socket UDP-style. I run and compile the code and it works just fine. If I then use "netcat -u " I am able to send messages from the client to the server but not the other way around. So what I want and what I have been trying to do is to read from stdin and printing it(all this running in a second thread). Making it a two-way communication. Anyone know what I need to fix? Thanks in advance.
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class NetcatUDP {
public static void main(String[] args) throws IOException {
int port = Integer.parseInt(args[0]);
byte[] buffer = new byte[65536];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
DatagramSocket socket = new DatagramSocket(port);
new Thread() {
#Override
public void run() {
// Read from stdin and send somehow?
}
}.start();
while (true) {
socket.receive(packet);
System.out.println(new String(packet.getData()).trim());
}
}
}
UDP is a connection-less protocol, which means you can send a message to anyone and receive a message from anyone with a single socket.
For the simple example you're using, you can actually use the same program for both endpoints. Besides reading in the local port number from the command line, read in the remote IP address and port as well. Then in your thread, you read from stdin using Console.readLine(), construct a DatagramPacket with the line read from the console, remote IP, and remote port, and send it with the existing socket you have.
I have a server/client application written in java. Basically when the client tries to connect to the server locally (127.0.0.1 as IP) everything works fine. However when I use my personal IP address (home address) I get a connection timeout error.
*I have portforwarded correctly, tested using port check tool
*I also checked using netstat -a in command prompt
*I am hosting on port 9005
here is some of my client code, where I assume I am doing somthing wrong:
public void run() throws UnknownHostException, IOException{
String serverAddress = "xx.xx.xx.xxx"; //My actual IP is here in the program
Socket socket = new Socket(serverAddress, 9005);
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
String playerName = JOptionPane.showInputDialog(
this,
"Choose Username:",
"Name Selection",
JOptionPane.PLAIN_MESSAGE);
out.println("NEW "+playerName);
I'm fairly new to server programing in Java, any suggestions would be appreciated.
I can post more code if requested, just didn't want to post a mountain of it.
thanks.
EDIT: here is some server code:
private final static int PORT = 9005;
public static void main(String[] args) throws Exception {
Server s = new Server();
s.setSize(50,100);
s.setDefaultCloseOperation(s.EXIT_ON_CLOSE);
s.setVisible(true);
System.out.println("Server running");
ServerSocket listener = new ServerSocket(PORT);
try {
while (true) {
new Handler(listener.accept()).start();
}
I have searched everywhere to find an answer for this question:
I have a TCP client on my android application that sends an message to the server which is written in Visual Basic .NET Framework 4.
Now i want to send an message from my server to the phone over 3g, it works on wifi and 3g..
private class startserver extends Thread
{
public void server() throws Exception
{
String clientSentence;
String capitalizedSentence;
ServerSocket welcomeSocket = new ServerSocket(8765);
while(true)
{
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient =
new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
clientSentence = inFromClient.readLine();
System.out.println(clientSentence.substring(1));
msgshower = clientSentence.substring(1);
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(MainActivity.this, "Received: " + msgshower , Toast.LENGTH_LONG).show();
}
});
capitalizedSentence = clientSentence.toUpperCase() + '\n';
outToClient.writeBytes(capitalizedSentence);
}
}
#Override
public void run() {
try {
server();
} catch (Exception e) {
e.printStackTrace();
}
}
I start it in the OnCreate method
Now i send a message with (VB.NET)
Private Sub sends(ByVal message As String)
Dim tcp As New TcpClient
tcp.Connect(connectedIP, 8765)
Dim bw As New IO.BinaryWriter(tcp.GetStream)
bw.Write(message)
bw.Close()
tcp.Close()
End Sub
On wifi it will arrive, on 3g it wont... any idea's how to do this?
How do other applications archive this?
I think you're having problem with the ip address asigned by your mobile phone operator. The fact that works on wifi, but not on 3G, I think that is because your mobile(when connected through 3G) doesn't have a public IP address.
When you use SocketServer in your mobile, you're opening a port a waiting for others to connect to it. If your IP address is not reachable from internet, it won't happen (it's like having a computer behind a firewall.)
Could you try to implement the server in the VB machine, assuming that it has a public reachable address? This way, the phone wouldn't act as a server, it wouldn't be necessary to have a reachable address, as long as the VB machine has one. Then, you should use Socket class to bind to the server ip and port.
Totally confused by your code list above..
If you want to host a server in VB.NET, you should not use TcpClient class but TcpListener and if you need a better performance, use Socket class directly.
At the Android client side, you should new Socket(server,servPort), when you want to send message, write the outputStream, and read the inputStream to receive message.