java-udp programming -sending message from server to the client - java

I made connection between server and client properly and i send message from client to the server,but how can i send messages from server to client.I mean how can i make server act like a client too.i tried to copy the client methods to the another class that server can invoke.but i couldnt then i tried to create a new package to use the client code in server class.any advices?
ps:Sorry about my english.
public class Entrance_Server extends JFrame{
JButton buton = new JButton("Create");
JButton buton2 = new JButton("Join");
JPanel butonpanel = new JPanel();
DatagramSocket sockServer = null;
DatagramSocket sockClient = null;
int port = 7777;
String s;
BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));
public Entrance_Server() {
setLayout(new GridLayout(2,1));
add(buton);
add(buton2);
buton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Choosing c = new Choosing();
c.start();
System.out.println("Server socket created. Waiting for incoming data...");
}
});
buton2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Choosing c = new Choosing();
c.start();
}
});
}
public static void main(String[] args){
Entrance_Server e = new Entrance_Server();
e.setSize(500,350);
e.setTitle("Welcome");
e.setLocationRelativeTo(null);
e.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
e.setVisible(true);
e.connect();
}
public void connect (){
try{
sockServer = new DatagramSocket(7777);
byte[] buffer = new byte[65536];
DatagramPacket incoming = new DatagramPacket(buffer, buffer.length);
while(true)
{
sockServer.receive(incoming);
byte[] data = incoming.getData();
String s = new String(data, 0, incoming.getLength());
//echo the details of incoming data - client ip : client port - client message
System.out.println(incoming.getAddress().getHostAddress() + " : " + incoming.getPort() + " - " + s);
s = "OK : " + s;
DatagramPacket dp = new DatagramPacket(s.getBytes() , s.getBytes().length , incoming.getAddress() , incoming.getPort());
sockServer.send(dp);
Entrance_Client_in_Server ec = new Entrance_Client_in_Server();
ec.connectc();
}
}catch(IOException i){
System.err.println("IOException " + i);
}
}
}

On your client u need to wait on the server response by using socket.Receive()
You can identify a client after he has send a packet to the server like you are doing. You can then indentify the client like this:
InetAddress address = packet.getAddress();
int port = packet.getPort();
And use it to send a packet back to the client, which will read the response using the socket.Receive();
For further information about Client/Server connection using UDP DatagramSockets check
Client-Server Datagram sockets

Related

java.net.SocketException: An established connection was aborted by the software in your host machine

I am trying to make a simple chat application using Java sockets, here is the code for the server:
public ServerSocket ss;
public ArrayList<Client> Clients = new ArrayList<Client>();
String Alphabets = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789";
public Server() throws IOException
{
ss = new ServerSocket(1111);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(null);
this.setResizable(false);
this.setSize(400,150);
this.getContentPane().setBackground(Color.BLACK);
this.setTitle("Server");
JLabel label = new JLabel("Server Running");
label.setForeground(Color.WHITE);
label.setBounds(15,25,350,60);
label.setFont(new Font(Font.SANS_SERIF,Font.PLAIN,50));
this.add(label);
this.setVisible(true);
while(true)
{
Socket socket = ss.accept();
DataOutputStream dout = new DataOutputStream(socket.getOutputStream());
String id = getId();
dout.writeUTF(id);
Client c = new Client(socket,id);
dout.close();
dout.flush();
}
}
String getId()
{
Random rand = new Random();
String id = "";
for(int i = 0;i < 6;i++)
{
char i3 = Alphabets.charAt(rand.nextInt(0,Alphabets.length()));
id += i3;
}
return id;
}
everything works fine, when the client connects he gets an id and is added to Clients
here is the code for the client connection:
public String Connect() throws UnknownHostException, IOException
{
mySocket = new Socket("localhost",1111);
DataInputStream din = new DataInputStream(mySocket.getInputStream());
String id = din.readUTF();
return id;
}
the problem is I get the exception java.net.SocketException: An established connection was aborted by the software in your host machine as I send input to the server, it doesn't send the first time I press send, and the next time I press send it give this exception, here is the code for sending input:
public void SendMessage(String msg) throws IOException
{
DataOutputStream dout = new DataOutputStream(s.getOutputStream());
dout.writeUTF(msg);
AddToMessages(Id + ": " + msg);
}
I'd be really glad if someone helps as I have been researching this problem for a long time and no one have seemed to come up to it.
Well I found out that restarting your pc solves the problem, this is kinda weird but it works!

How to group 2 udp clients?

What i'm trying to do is group 2 clients and make them communicate with eachother. So if 2 clients are connected they would only be able to communicate with eachother and if a third client got connected it would not be able to communicate with the 2 other clients but it would create another group of 2 clients and so on... Right now if a client sends a message it send it over to all clients but i don't know how to make it work like described above. Messages are send from client by typing something in console.
server:
public class Server extends Thread{
public final static int PORT = 7331;
private final static int BUFFER = 1024;
private DatagramSocket socket;
private ArrayList<InetAddress> clientAddresses;
private ArrayList<Integer> clientPorts;
private HashSet<String> existingClients;
public Server() throws IOException {
socket = new DatagramSocket(PORT);
System.out.println("[SERVER] UDP server successfully launched on port " + PORT);
clientAddresses = new ArrayList<InetAddress>();
clientPorts = new ArrayList<Integer>();
existingClients = new HashSet<String>();
}
public void run() {
byte[] buf = new byte[BUFFER];
while (true) {
try {
//resets buffer so only new messages get displayed
Arrays.fill(buf, (byte) 0);
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
String content = new String(buf, buf.length);
InetAddress clientAddress = packet.getAddress();
int clientPort = packet.getPort();
String id = clientAddress.toString() + "," + clientPort;
if (!existingClients.contains(id)) {
existingClients.add(id);
clientPorts.add(clientPort);
clientAddresses.add(clientAddress);
}
System.out.println(id + " : " + content);
byte[] data = (id + " : " + content).getBytes();
for (int i = 0; i < clientAddresses.size(); i++) {
InetAddress cl = clientAddresses.get(i);
int cp = clientPorts.get(i);
packet = new DatagramPacket(data, data.length, cl, cp);
socket.send(packet);
}
} catch (Exception e) {
System.err.println(e);
}
}
}
public static void main(String args[]) throws Exception {
Server s = new Server();
s.start();
}
}
clients:
public class Client implements Runnable {
public static void main(String args[]) throws Exception {
String host = "127.0.0.1";
DatagramSocket socket = new DatagramSocket();
//handles the receiving part for every client (incoming packets to clients)
MessageReceiver r = new MessageReceiver(socket);
Client s = new Client(socket, host);
Thread rt = new Thread(r);
Thread st = new Thread(s);
rt.start();
st.start();
}
public final static int PORT = 7331;
private DatagramSocket sock;
private String hostname;
Client(DatagramSocket s, String h) {
sock = s;
hostname = h;
}
//sending clients socket to server
private void sendMessage(String s) throws Exception {
//getting bytes from message
byte buf[] = s.getBytes();
//getting hostname from server
InetAddress address = InetAddress.getByName(hostname);
//setting up packet
DatagramPacket packet = new DatagramPacket(buf, buf.length, address, PORT);
//sending packet to server
sock.send(packet);
}
public void run() {
//connected boolean is used to send a greetings message once for every new client that has joined
boolean connected = false;
do {
try {
sendMessage("GREETINGS");
connected = true;
} catch (Exception e) {
}
} while (!connected);
//reads from the console
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
while (true) {
try {
while (!in.ready()) {
Thread.sleep(100);
}
//sends message from console to server
sendMessage(in.readLine());
} catch (Exception e) {
System.err.println(e);
}
}
}
}
//this class handles receiving part of clients
class MessageReceiver implements Runnable {
DatagramSocket sock;
byte buf[];
MessageReceiver(DatagramSocket s) {
sock = s;
buf = new byte[1024];
}
public void run() {
while (true) {
try {
DatagramPacket packet = new DatagramPacket(buf, buf.length);
sock.receive(packet);
String received = new String(packet.getData(), 0,
packet.getLength());
System.out.println(received);
} catch (Exception e) {
System.err.println(e);
}
}
}
}
What youre trying is a message broadcast or a message-repeater-client.
broadcasting is implemented on network layer (using brodcast the local network broadcast adress).
And if you implementing it that way, you'll flood your network, when you have more than 2 clients. Best regards to your network admin. ;-)

UDP Broadcasting Client and Server not detecting each other

I'm currently trying to follow this sample code that Michiel De Mey created on detecting LAN IP'.
See link for his code: https://demey.io/network-discovery-using-udp-broadcast/
Anyways, i tried following it and i basically got what he got. It works when i run both server and client on my pc, but when i run the server from my PC, and the client from my android application, the client doesn't register a reply from the server, or maybe doesn't even get anything out there. I'm rather unsure really.
I just figured that it might be because my stationary computer is linked to the network via a cable, while the the laptop im currently running the android emulator on is connected to the network by wifi, with a router separating the two.
Why does it not work via my local area network? (I'm connected correctly, and i set the StrictMode ThreadPolicy in android to permitAll), so i know that aint the problem.
Thanks in advance!
For the server side i have this piece of code:
public class DiscoveryThread implements Runnable {
public static void main(String[] args){
Thread discoveryThread = new Thread(DiscoveryThread.getInstance());
discoveryThread.start();
}
DatagramSocket socket;
#Override
public void run() {
try {
//Keep a socket open to listen to all the UDP trafic that is destined for this port
socket = new DatagramSocket(6789, InetAddress.getByName("0.0.0.0"));
socket.setBroadcast(true);
while (true) {
System.out.println(getClass().getName() + ": Ready to receive broadcast packets!");
//Receive a packet
byte[] recvBuf = new byte[15000];
DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
socket.receive(packet);
//Packet received
System.out.println(getClass().getName() + ": Discovery packet received from: " + packet.getAddress().getHostAddress());
System.out.println(getClass().getName() + ": Packet received; data: " + new String(packet.getData()));
//See if the packet holds the right command (message)
String message = new String(packet.getData()).trim();
if (message.equals("DISCOVER_FUIFSERVER_REQUEST")) {
byte[] sendData = "DISCOVER_FUIFSERVER_RESPONSE".getBytes();
//Send a response
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, packet.getAddress(), packet.getPort());
socket.send(sendPacket);
System.out.println(getClass().getName() + ": Sent packet to: " + sendPacket.getAddress().getHostAddress());
}
}
} catch (IOException ex) {
Logger.getLogger(DiscoveryThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static DiscoveryThread getInstance() {
return DiscoveryThreadHolder.INSTANCE;
}
private static class DiscoveryThreadHolder {
private static final DiscoveryThread INSTANCE = new DiscoveryThread();
}
}
Client side:
public class UDPClient {
DatagramSocket c = null;
public void connect(){
try{
c = new DatagramSocket();
c.setBroadcast(true);
byte[] sendData = "DISCOVER_FUIFSERVER_REQUEST".getBytes();
try{
byte[] buf = new byte[256];
InetAddress ip = InetAddress.getByName("255.255.255.255");
DatagramPacket packet = new DatagramPacket(sendData,sendData.length,ip,6789);
c.send(packet);
System.out.println(getClass().getName() + ": Request packet sent to: 255.255.255.255 (DEFAULT)");
}catch(IOException e){
e.printStackTrace();
}
// Broadcast the message over all the network interfaces
Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface networkInterface = (NetworkInterface) interfaces.nextElement();
if (networkInterface.isLoopback() || !networkInterface.isUp()) {
continue; // Don't want to broadcast to the loopback interface
}
for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) {
InetAddress broadcast = interfaceAddress.getBroadcast();
if (broadcast == null) {
continue;
}
// Send the broadcast package!
try {
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, broadcast, 6789);
c.send(sendPacket);
} catch (Exception e) {
}
System.out.println(getClass().getName() + ": Request packet sent to: " + broadcast.getHostAddress() + "; Interface: " + networkInterface.getDisplayName());
}
}
System.out.println(getClass().getName() + ": Done looping over all network interfaces. Now waiting for a reply!");
//Wait for a response
byte[] recvBuf = new byte[15000];
DatagramPacket receivePacket = new DatagramPacket(recvBuf, recvBuf.length);
c.receive(receivePacket);
//We have a response
System.out.println(getClass().getName() + ": Broadcast response from server: " + receivePacket.getAddress().getHostAddress());
//Check if the message is correct
String message = new String(receivePacket.getData()).trim();
if (message.equals("DISCOVER_FUIFSERVER_RESPONSE")) {
//DO SOMETHING WITH THE SERVER'S IP (for example, store it in your controller)
System.out.println("Server's IP: "+receivePacket.getAddress());
}
//Close the port!
c.close();
} catch (IOException ex) {
// Logger.getLogger(LoginWindow.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

C# server Socket to Android Socket over NAT

The Android app is behind a NAT (3G connection) , while the server is on a public IP.
The Android app can connect to the server socket and send data (via Socket/TCPclient on android) but the server cannot connect to the Android port because of the NATs
(server getting "... has failed to respond "ip_adress_of_android : port_that_is_open_and_listening_on_android".
Is there anyway to overcome this, or some parameters I can use in order for the server connection attempt to reach it's destination over the NATs without using a custom library? - or could you please point me to an easy to implement method, I don't have time to study and integrate a complicated 3rd party library
Here is a sample of how my server code works:
int port_server, port_android; // used to declare used ports by the server and android
Socket server_socket, client_socket; //sockets used to receive and send data
server_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server_socket.Bind(new IPEndPoint(IPAddress.Any, port_server));
server_socket.Listen(0);
public void listen()
{
server_socket.BeginAccept(new AsyncCallback(AcceptCallback), null);
}
private void AcceptCallback(IAsyncResult AR)
{
client_socket = server_socket.EndAccept(AR);
buffer = new byte[client_socket.ReceiveBufferSize];
client_socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
}
private void ReceiveCallback(IAsyncResult AR)
{
listen(); // to continue listening to the port
// code that does something with the data
send_string("Take this"); // sends a string to android
}
public void send_string(string notif)
{
string ip_client = client_socket.RemoteEndPoint.ToString();
string ip_client2 = (ip_c.Split(':'))[0];
TcpClient client = new TcpClient(ip_client, port_android);
Byte[] notifi = System.Text.Encoding.ASCII.GetBytes(notif);
NetworkStream stream = client.GetStream();
stream.Write(notifi, 0, notifi.Length);
stream.Close();
client.Close();
}
I should note that they work both ways when on a LAN, so the code is working, I only need to modify is so that it can reach android targets over NATs.
Something like this
class Program
{
int port_server = 42424;
Socket server_socket;
public Program()
{
server_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server_socket.Bind(new IPEndPoint(IPAddress.Any, port_server));
server_socket.Listen(0);
}
public void Listen()
{
while (true)
{
var client = server_socket.Accept();
var buffer = new byte[client.ReceiveBufferSize];
client.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), Tuple.Create(client, buffer));
}
}
private void ReceiveCallback(IAsyncResult AR)
{
var state = (Tuple<Socket, byte[]>)AR.AsyncState;
var client = state.Item1;
var buffer = state.Item2;
byte[] notifi = System.Text.Encoding.ASCII.GetBytes("Take this");
client.Send(notifi);
client.Close();
}
static void Main(string[] args)
{
var programm = new Program();
programm.Listen();
}
}
client part
using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
client.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 42424));
client.Send(new byte[] {1, 2, 3}, SocketFlags.None);
byte[] bt = new byte[256];
client.Receive(bt, 256, SocketFlags.None);
}

java udp packet merging

I've got a strange problem while practising with UDP in Java. If I send multiple UDP handshake packets of different data lengths between servers, the UDP packets merge. I'm using a timer to send the handshakes between the servers.
public class UDPtest {
public static UDPtest test = new UDPtest();
public static byte[] buffer = new byte[1024];
public static InetAddress host = null;
Timer timer = new Timer();
TimerTask ttimer = new TimerTask() {
public void run() {
//System.out.println("time");
}
};
public static void main(String args[]) throws Exception {
DatagramSocket sendSocket = new DatagramSocket();
DatagramSocket receiveSocket = new DatagramSocket(Integer.parseInt(args[1]));
String s = "SEND "+args[0];
host = InetAddress.getByName("localhost");
buffer = s.getBytes();
DatagramPacket handshake = new DatagramPacket(buffer, buffer.length, host, Integer.parseInt(args[2]));
test.RouteTimer(receiveSocket,handshake);
while (true) {
DatagramPacket receivePacket = new DatagramPacket(buffer,buffer.length);
receiveSocket.receive(receivePacket);
String receiveString = new String(receivePacket.getData());
if (receiveString.substring(0,1).matches("A")) {
System.out.println(receiveString);
continue;
}
else {
System.out.println(receiveString);
String temp = "A "+args[0];
buffer = temp.getBytes();
DatagramPacket sendPacket = new DatagramPacket(buffer, buffer.length, host, Integer.parseInt(args[2]));
sendSocket.send(sendPacket);
}
}
}
public void RouteTimer(final DatagramSocket socket, final DatagramPacket handshake) {
Timer timer = new Timer();
TimerTask ttimer = new TimerTask() {
#Override
public void run() {
try {
socket.send(handshake);
}
catch (Exception e) {
}
}
};
timer.scheduleAtFixedRate(ttimer, 1000, 5000);
}
}
For example: If I have server X and Y, the expected output for server X would be:
SEND X
A X
SEND X
A X
but the output becomes:
SEND Y
A Y
SEN
A Y
I'm trying to understand why this happens, and how to fix the problem.
Any help would be appreciated.
If I send multiple UDP handshake packets of different data lengths between servers, the UDP packets merge.
No they don't.
String receiveString = new String(receivePacket.getData());
Your problem is here. You are ignoring the length of the packet. It should be:
String receiveString = new String(receivePacket.getData(), receivePacket.getOffset(), receivePacket.getLength());

Categories