I am new to java sockets, I am trying to create a simple UDP transmission using client-server. My problem now is the server is running the infinite loop and not sending message over to the client. Sorry if i did some stupid mistake, thanks
Server:
import java.net.*;
import java.util.*;
class EchoServer {
public static void main( String args[] ) throws Exception {
DatagramSocket socket = new DatagramSocket(54373);
DatagramPacket packet = new DatagramPacket(new byte[512],512);
String temp = "Hello client";
byte[] buffer = temp.getBytes();
while (true) {
socket.receive( packet );
System.out.println("Received from client");
DatagramPacket packet2 = new DatagramPacket(buffer,buffer.length,InetAddress.getByName("127.0.0.1"),54373);
socket.send( packet2 );
}
}
}
Client:
import java.net.*;
import java.util.*;
class EchoClient {
public static void main( String args[] ) throws Exception {
DatagramSocket socket = new DatagramSocket();
socket.setSoTimeout( 5000 );
byte[] buffer = "Hello Server".getBytes();
DatagramPacket packet = new DatagramPacket(buffer,buffer.length,InetAddress.getByName("127.0.0.1"),54373);
socket.send( packet );
DatagramPacket packet2 = new DatagramPacket(new byte[512],512);
socket.receive(packet2);
System.out.println("Received from server");
}
}
However, my server is able to send the original "packet" instead of packet2
Your server is sending back to itself. Instead of using its own port number when constructing the reply datagram, it should use the one that's already in the request datagram. And the IP address. In fact it should just send the request datagram as-is, as it's an echo server: no need to construct another one.
If the protocol changes the idea is to use the setData() method on the request to put the reply into it, again rather than creating a new datagram.
Related
I have created a very very basic java server with tutorials. The goal is to let gamemaker studio 2 clients connect and communicate with that server. I have more experience with GML.
So the server is starting(java) up and the client(GMS2) is connecting succesfully. I have buildin some checks to make sure. If the client send a message to the server, the server never gets it, until the clients disconnect.
this is the java code:
import java.net.*;
import java.io.*;
public class GameServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(6666);
Socket client = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
out.println("hello gamemaker studio: "); //the clients receive this message
while(true) {
System.out.println("in while loop");//the server console prints this message
String string = in.readLine();//keeps stuck on this
//after client disconnect, all messages the client has sent are displayed in the console
System.out.println("reading string:" + string);
if (string == null) { break; }
out.println("we have received this answer: " + string );
System.out.println("stopped");
}
}
}
For some reason i don't know it is keeps stuck on this line:
String string = in.readLine();
I crafted a java client to test it. Everything works fine with a java client.
So there has to be something wrong with the gamemaker code
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 want to send and receive data (unicode utf-8 strings through udp sockets, DatagramSocket. I have been looking into SO for answers, but could only find solutions for TCP transfer using InputStream and like.
Is there a similar way for UDP?
UDP Client
package testsocket;
import java.io.IOException;
import java.net.*;
public class TestSocketSender {
private DatagramSocket sock;
public static void main(String[] args) {
new TestSocketSender();
}
public TestSocketSender(){
try {
sock = new DatagramSocket();//, Inet4Address.getLocalHost());
sendData("Hello World\u00A9");
} catch (SocketException ex) {
ex.printStackTrace();
} catch(IOException e){
e.printStackTrace();
}
}
private void sendData(String data) throws IOException{
DatagramPacket datagram = new DatagramPacket(data.getBytes("utf-8"), data.length(), InetAddress.getLocalHost(), 5060);
sock.send(datagram);
}
}
UDP Server
package testsocket;
import java.io.IOException;
import java.net.*;
public class TestSocketListerner {
private DatagramSocket sock;
public static void main(String[] args) {
new TestSocketListerner();
}
public TestSocketListerner(){
try {
sock = new DatagramSocket(5060);//, Inet4Address.getLocalHost());
while(true){
System.out.println(recvData());
}
} catch (SocketException ex) {
ex.printStackTrace();
} catch(IOException e){
e.printStackTrace();
}
}
private String recvData() throws IOException{
byte[] data = new byte[100];
DatagramPacket datagram = new DatagramPacket(data , data.length);
sock.receive(datagram);
return new String(datagram.getData(),datagram.getOffset(),datagram.getLength(),"utf-8");
}
}
UDP is a datagram-based protocol. It means that you can only send a fixed amount of data without any warranties about the data being delivered. The packet may be lost, the data inside may be corrupted because even the CRC is not mandatory in UDP and even worse - the packets you send may be reordered on the receiving side because of the multiple routers along the packet's way.
To implement something which looks like a Stream using the UDP channel is not trivial, but surely possible. You have to split the data into small portions (the MTU of the system), pack them with some recovery information, assign sequence numbers to each packet and provide some mechanism to reask packets which are lost on the way.
send the length first.
Have your sender pack the bytes first, then send the length and then the string. I suggest you pack it into four bytes.
Have your reader, read 4 bytes, then reconstruct the length, then read the string.
You can then handle the problems of data not arriving and timing out, etc...
I am setting up a simple TCP Client Server interaction in java.
Server:
The server is a desktop client written in Java:
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
class TCPServer
{
public static int PORT_NUMBER = 6129;
public static void main(String argv[]) throws Exception
{
String clientMessage;
ServerSocket welcomeSocket = new ServerSocket(PORT_NUMBER);
while (true)
{
Socket connectionSocket = welcomeSocket.accept();
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
clientMessage = inFromClient.readLine();
System.out.println("Received: " + clientMessage);
outToClient.writeBytes("I received this: "+ clientMessage +"\n");
}
}
}
Client:
The client is an android app that connects to the server with TCP. In the client I have a method sendMessage(String msg) which attempts to send a message to the server.
public static void sendMessage(String msg) throws IOException
{
if (mainSocket == null)
{
return;
}
if (!mainSocket.isConnected())
{
connectSocket();
}
PrintWriter output = new PrintWriter( mainSocket.getOutputStream());
output.println(msg);
output.flush();
System.out.println(msg);
}
The problem is, the server receives the first message, but any subsequent messages won't show up at all. When I close the client down, all of a sudden all the other messages show up at once in the server.
This is what the server sees:
Received: message 1
No activity for a long time...
Then I shut down the client
Received: message 2 message 3 message 4 message 5 etc..
I put a println in the sendMessage() method, and the method itself is being called in real time.
You need to explicitly close() your PrintWriter on the client side each time you send a message. Same on the server side when you are done reading inFromClient, and again when you are done writing to outToClient.
See also this basic example, they explain the basic workflow quite nicely:
However, the basics are much the same as they are in this program:
Open a socket.
Open an input stream and output stream to the socket.
Read from and write to the stream according to the server's protocol.
Close the streams.
Close the socket.