Client Socket as the listener? - java

I need all my clients attached to a server to be socket listeners. The server will attempt to connect to a specific client and instruct it to preform a various task via a socket message. So my question is, can my Java Client be the ServerSocket and listen for Server requests? And is it possible for a webpage loaded on a client machine to know the clients IP address to send the message too. We have an application running on our server that has many clients attached and when a button is pressed on the clients webpage it will attempt to connect with this client and send a message to it. Most of the time servers are listeners, but in our case we need just opposite where the client is listener waiting for server requests. But the server needs to know what the client IP address is to establish the connection since our clients are attached via DHCP.
Btw,
All our clients are basically running a webpage from our server and each client has it own PC. The thing I need to do is control a USB device on each client machine. I have control over the website software, so my goal was to use sockets to do this since controlling a clients external hardware is very difficult remotely. So what I was going to do is write a Java app and that runs on the client machine acting as a listener which when someone presses a button on the webpage the server will attempt to connect to the client machine and send the message down to it. I’m just not sure how to handle this from the server side, so it knows what client it’s talking too since I don’t want to broadcast the message to all clients, but only the one the button was pressed on, keep in mind each client is attached via DHCP addressing, so I can't hardcode the hostID. I can attach java/groovy or ajax scripts to the button event on the server side, but I’m not sure how to setup the socket protocol on the server to make this work.
Here is an example of a socket connection I could use on the client / server side, but I need to know the clients DHCP IP address is to make it work properly.
Server side requesting client task
public void requestSocket()
{
Socket socket = null;
private BufferedReader in = null;
private PrintWriter out = null;
//Create socket connection for server
String serverAddress = "localhost"; // Needs to be the client DHCP IP address.
try
{
socket = new Socket(serverAddress, 4444);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
catch (UnknownHostException e)
{
System.out.println("Unknown host: " + serverAddress);
System.exit(1);
}
catch (IOException e)
{
System.out.println(e);
System.out.println("No I/O");
System.exit(1);
}
}
Client side listener acting as the server
public void listenSocket()
{
int portNumber = 4444;
ServerSocket server = null;
Socket client = null;
BufferedReader in = null;
PrintWriter out = null;
try
{
client = new ServerSocket(portNumber);
}
catch (IOException e)
{
System.out.println("Could not listen on port " + portNumber);
System.exit(-1);
}
try
{
server = client.accept();
}
catch (IOException e)
{
System.out.println("Accept failed :" + portNumber);
System.exit(-1);
}
try
{
in = new BufferedReader(new InputStreamReader(server.getInputStream()));
out = new PrintWriter(server.getOutputStream(), true);
} catch (IOException e) {
System.out.println("Read failed");
System.exit(-1);
}
while(true)
{
try
{
line = in.readLine();
//Send data back to client
out.println(line);
}
catch (IOException e)
{
System.out.println("Read failed");
System.exit(-1);
}
}
}
Can anyone help answer these questions?

First: what are your clients? Java Client or Webpage in browser?
Second: if it is JavaClient it can be only ServerSocket in it to listen what your server will tell and Server must know IP and port of each clients to do that.
Third: for Java Client actually JMS with Topic is there for such tasks. Server publishes message, while clients listen and do with message what is needed.
and Forth:
If it is a webpage there is only one way - from JavaScript (or auto-refresh mechanism) browser can ask Server periodically (by timer) for new messages. With HTML there is no way for the server to initiate any actions on client browser.
It is always request-response.
Updated:
try something like that:
<html>
<head>
<title>Test Loop Back</title>
</head>
<body>
<form action="http://localhost:4444" id=in_form>
<table>
<tr>
<td>
<label>IN_MSG:</label>
</td>
<td>
<input type="text" name="IN_MSG" id="IN_MSG"/>
</td>
</tr>
</table>
<button type="submit" formmethod="post">Post Something</button>
</form>
</body>
</html>
and see what you get in your background Java listening on port 4444. Mayb it can be enough? you can pass anything you may need as separate input fields and them can be hidden as well as whole form can be invisible...
If you need some data from server prepared for background java think the way on picture to avoid communication from server to background java.
main point is to avoid direct communication from server to background java. All passes through the browser, so no pain with IP, ports, proxy, security etc. Browser and javascript on webpage take care of all...

Related

How do i get the port and address of client without receiving data from it first?

I'm making a simple UDP chat program, and i would like the server to be able to send to the client without receiving data from it first. Normally, when it receives data from the client, the server gets the IP and port of the client, so it can communicate with it.
My server code:
package com.ageforce;
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class ChatServer {
DatagramSocket server;
byte[] receivedData = new byte[1024];
Scanner scanner = new Scanner(System.in);
byte[] sentData;
DatagramPacket dp2 = new DatagramPacket(receivedData, receivedData.length);
public ChatServer() throws SocketException {
server = new DatagramSocket(7000);
}
public static void main(String[] args) throws SocketException {
ChatServer cs = new ChatServer();
Thread receiveMessage = new Thread(() -> {
while (true) {
try {
cs.server.receive(cs.dp2);
} catch (IOException e) {
e.printStackTrace();
}
String storedData = new String(cs.dp2.getData());
System.out.println(storedData);
}
});
Thread sendMessage = new Thread(() -> {
while (true) {
String sentMessage = cs.scanner.nextLine();
cs.sentData = sentMessage.getBytes();
// This is the area of the code where the server gets IP and port of client from the received data. I'd like this to be changed.
InetAddress getIP = cs.dp2.getAddress();
int port = cs.dp2.getPort();
DatagramPacket dp3 = new DatagramPacket(cs.sentData, cs.sentData.length, getIP, port);
try {
cs.server.send(dp3);
} catch (IOException e) {
e.printStackTrace();
}
}
});
sendMessage.start();
receiveMessage.start();
}
}
Is it possible to do this? Any reply is greatly appreciated.
How do i get the port and address of client without receiving data from it first?
UDP does not afford that possibility. It is a connectionless protocol, so the server doesn't even know that there is a client until it receives a message from it.
You could conceivably create some kind of preliminary application-level protocol whereby the client announces itself to the server before sending it any chat data, but nothing of the sort is part of UDP itself, and if that's something you want then you should consider using TCP instead, which does have a built-in concept of establishing a connection before sending any data.
In order to send an UDP message to something, you need to know the IP and port number to send it to. How? Well, you tell me.
The way your protocol works right now is that the clients know your hostname (which they let their system turn into an IP automatically), and the port number is hardcoded in the client app. The server knows which IP and port to send data back to by checking the 'sender' IP/port when it receives a call.
If you don't like your current protocol you'll need to figure out a different way to answer this question.
Even if you find a way, you'll find that this is mostly useless. The vast majority of end-users intentionally do not have a so-called publically routable IP address. You cannot reach them by design. In your current protocol, that IP/port combo you send back to isn't really the sending computer at all. It's some router, for example the router in their home. That router saw the outgoing UDP packet and is remembering for a while: Any traffic coming in on that port is supposed to go to that computer in this house.
Short of completely crazy stuff such as 'hole punching' (which skype used for a while, not sure if they still do, it's a complicated hack that doesn't always work and is surely not what you want here - you can search the web for that term), there's simply nothing you can do here. end-user systems aren't servers and cannot be reached like this.
Your run-of-the-mill chat apps will always have clients ping the server and then just keep that connection open as long as they can.

Sockets - Java Client and NodeJS Server

I am trying to connect a simple Java client to a NodeJS server but unfortunately things aren't working out that well. I took the client code from the Java Doc and only changed the hostname and port. Now my server is running on the same computer as the client and the port is 4555. If I do not have the same port on the client and the server then an error get thrown, I have checked this. Also if I change the hostname to something arbitrary(not localhost) in the client then a error get thrown. This suggests that if I am unable to connect then errors are getting thrown. The funny thing is that if I have the port set to 4555 and the hostname to "localhost" I am not getting any of theese errors and my client is working fine which makes me think that I am getting a connection but I am not getting the message "client connected" on my server side. Any suggestions?
The server code:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var port = 4555;
app.get('/', function(req, res)
{
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket)
{
//When I connect to to localhost:4555 through the web browser(chrome)
//this message is actually shown so the connection works there.
console.log('client connected');
});
http.listen(port, function()
{
//Message shown on program start
console.log("app running");
});
The client code:
import java.io.*;
import java.net.*;
public class Main
{
public static void main(String[] args) throws IOException
{
String hostName = "localhost";
int portNumber = 4555;
try (
Socket echoSocket = new Socket(hostName, portNumber);
PrintWriter out =
new PrintWriter(echoSocket.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(echoSocket.getInputStream()));
BufferedReader stdIn =
new BufferedReader(
new InputStreamReader(System.in))
) {
String userInput;
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
System.out.println("echo: " + in.readLine());
}
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + hostName);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to " +
hostName);
System.exit(1);
}
}
}
To get your "client connected" message, you need a successful socket.io connection. socket.io is a messaging data format built on top of the webSocket protocol. So to successfully connect to a socket.io server, you need a socket.io client. You cannot connect to a socket.io server with a plain TCP client which is what you appear to be trying to do.
Just to give you an idea of what's likely happening here, a socket.io expects an incoming webSocket connection (which starts life as an HTTP connection which is then "upgraded" to the webSocket protocol because of some special headers on the incoming HTTP connection. The socket.io adds its own data format on top of the webSocket data frame. So, only a socket.io client can talk to a socket.io server. The socket.io server is rejecting the incoming connection after it connects because the initial data on the connection does not fit the proper format.
See Writing webSocket Servers to give you an idea what is involved in connecting to a webSocket server. There's an initial connection request format using HTTP, there's an upgrade request, there are security headers, then there's an upgrade to the webSocket protocol, then there's a data frame format with encryption and then socket.io then adds a message data format on top of all this. When your client tries to connect to a server expecting all this, the server just says this is garbage and drops the connection.
If you want a plain TCP connection, then you can use a plain TCP server in your node.js server and connect to that. You want a socket.io connection, then you can get a socket.io client library for Java and use that instead of your plain Socket to talk to your socket.io server.

How to run a simple socket server that allows incoming connections?

I am trying to build a very simple socket server in JAVA that my Flash application can listen to. I am using this tutorial. Everything seems to be working - the JAVA code is compiled and the server is running.
My question is: how can external applications send messages to this server using just an IP address and a port number? My goal is that flash can listen to socket messages sent by an external application.
The Java code:
import java.io.*;
import java.net.*;
class SimpleServer {
private static SimpleServer server;
ServerSocket socket;
Socket incoming;
BufferedReader readerIn;
PrintStream printOut;
public static void main(String[] args) {
int port = 8080;
try {
port = Integer.parseInt(args[0]);
} catch (ArrayIndexOutOfBoundsException e) {
// Catch exception and keep going.
}
server = new SimpleServer(port);
}
private SimpleServer(int port) {
System.out.println(">> Starting SimpleServer");
try {
socket = new ServerSocket(port);
incoming = socket.accept();
readerIn = new BufferedReader(
new InputStreamReader(
incoming.getInputStream()));
printOut = new PrintStream(incoming.getOutputStream());
printOut.println("Enter EXIT to exit.\r");
out("Enter EXIT to exit.\r");
boolean done = false;
while (!done) {
String str = readerIn.readLine();
if (str == null) {
done = true;
} else {
out("Echo: " + str + "\r");
if(str.trim().equals("EXIT"))
done = true;
}
incoming.close();
}
} catch (Exception e) {
System.out.println(e);
}
}
private void out(String str) {
printOut.println(str);
System.out.println(str);
}
}
Maybe I don't understand correctly your problem description, but if you create the server in Java, it listens to its port and not your Flash application. If you want your Flash application to wait for messages from other applications, it must have a server role and listen to a TCP port the same way as this Java server does.
You can connect to and test the given Java server easily by telnet program (available in all operating systems) by providing a host name or an IP address and a port as parameters:
telnet 127.0.0.1 8080
Any other application can connect in a similar way, using just a hostname/IP address and a port. For example in Java, you can create a client socket:
Socket clientSocket = new Socket("localhost", 8080);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
By not specifying an IP address for your socket, it will listen on 0.0.0.0 (all interfaces).
In fact, that will usually be your computer's IP / the server's IP.
Assuming that your application runs on your computer at home, there are three cases that cover most of the connection situations:
Connecting from the same machine:
Use 127.0.0.1:8080
Connecting from the same LAN (e.g. your brother's PC):
Use your LAN IP (e.g. 192.168.1.4:8080)
Connecting from WAN (outside your routers LAN) (internet e.g.):
Use your WAN IP.(e.g. 84.156.74.194). There are plenty websites, that tell you your WAN IP like this
You may have to setup your router, to forward the port 8080 to your PC
For simple connection tests, one could use a telnet client.
I think you are missing the point of client/server socket applications.
If you are building the socket server (with whatever programming language you chose), you will then need to connect with (a) socket client(s) to this server. After a connection is successfully established (persistent) between the client and the server, you can start what ever kind of communication you have implemented between them.
The server always acts as the passive, the client as active part in a socket server/client constellation.
I was checking the link that you are referring to. In that, the procedure to create a stand-alone server is mentioned which is the code that you have pasted as well.
According to the link, the application acts as the client and uses the XMLSocket methods to connect to this server. This application is the flash application that you are talking about. As mentioned in the link, by using the following code any flash application can connect and talk to the server:
var xmlsock:XMLSocket = new XMLSocket();
xmlsock.connect("127.0.0.1", 8080);
xmlsock.send(xmlFormattedData);
When you mention
My goal is that flash can listen to socket messages sent by an external application.
its actually the flash application that is the client and it cannot listen unless programmed to act as a server. I hope this provides some clarity!

How client know which socket connect to?

I am using Java to do the socket programming as below.
Client program is as below:
Socket MyClient;
try {
MyClient = new Socket("Machine name", PortNumber);
}
catch (IOException e) {
System.out.println(e);
}
Server program is as below:
ServerSocket MyService;
try {
MyServerice = new ServerSocket(PortNumber);
}
catch (IOException e) {
System.out.println(e);
}
Socket clientSocket = null;
try {
clientSocket = MyService.accept();
}
catch (IOException e) {
System.out.println(e);
}
Now my question is if I run more than one thread to open several sockets in one port (as the server code above), how my client program know which socket it is connecting to?
Your client connects to the Servers port. So all clients will be having the same code
MyClient = new Socket("Machine name", <port where server is listening>);The port opened at client side is not important. The client will get a free port available in his OS.
how my client program know which socket it is connecting to?
The question doesn't make sense. It doesn't 'connect to a socket' at all, it connects to a listening port, and there is only one of those. Your server only accepts one client, so the second and subsequent threads will get an undefined behaviour ranging from a ConnectException to a ConnectionException to nothing, most probably the latter.
Your application knows it because you set it up with a specific port. There is no "auto discovery" built into TCP/IP, it's up to you to pick a server-port and make sure you set your clients up to connect to that port. Either you hard-code this into your client application or, better yet, have it in some configuration file you include with the client.
This is why you have a bunch of "known ports", like http is port 80. This means that a browser will always connect to port 80 on a web-server, unless you explicitly indicate another port in the URL.

how can make two clients chat with each other?

this is not my homework(my homework is just about doing chat with a client and server which it works correctly especially with your help[:-)]
but I want to make two clients chat with each other,I don't know that when i get text from the first one how can I send that text to the other client.would you please help me.thanks.
public class MainServer {
static Socket client = null;
static ServerSocket server = null;
public static void main(String[] args) {
System.out.println("Server is starting...");
System.out.println("Server is listening...");
try {
server = new ServerSocket(5050);
} catch (IOException ex) {
System.out.println("Could not listen on port 5050");
System.exit(-1);
}
try {
boolean done = false;
while (!done) {
client = server.accept();
System.out.println("Client Connected...");
BufferedReader streamIn = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter streamOut = new PrintWriter(client.getOutputStream(),true);
String line = streamIn.readLine();
if (line.equalsIgnoreCase("bye")) {
streamIn.close();
client.close();
server.close();
done = true;
} else {
System.out.println(line);
streamOut.println(line);
}
}
} catch (IOException e) {
System.out.println("IO Error in streams " + e);
}
}}
That's it, your two "clients" will both act as client and server :
Listening to incoming things on a socket and sending things over an other sockets.
On the server, you can keep a Set of all the clients that are currently connected to the server. The server should listen for messages (can do this with a ServerSocket, and clients connect with normal Sockets). Each time the server receives a message, it sends this message back to all clients in the Set, and the clients display the message.
EDIT: this is for a client-server system, where clients connect to a central server instead of directly to each other. If you want to do direct client-to-client, one of them will just have to act as the server, and you'll need to implement a chat UI in both.
Here is a very simple, ~100 line, GUI chat program.
Have a look at Building an Internet chat system.
This explains how to write simple Clients and a Server with Java.
Unless you want to get into really complicated P2P discovery protocols, you would have to have a server to act at least as an intermediary.
In order to establish a direct client to client connection, the clients would need to know each others IP addresses. To do this, each client would first connect and "register" itself with a central server.
When a client wants to talk to another client, it would ask for that client's address from the server, then establish a connection directly with that client. So each client is acting both as a client (establishing connections with the server and other clients) and as a server (accepting connections from other clients).
It seems simple in theory, but in practice it gets more complicated. For example, what if the client you want to connect to is behind a firewall? You could have a hole in the firewall for incoming connections to get through, or you could fall back to having the communication go through the server, or if one of the clients is behind a firewall and the other isn't, the server could mediate the connection in the opposite direction.
Basically, there are two approaches:
One Chat server that receives all messages and distributes/forwards them to the clients (xmpp/jabber works this way)
One server that connects clients directly. Like on peer-to-peer networks
Looking back at your previous work, I think, the first approach is more feasible.
The server will offer one port where new clients can connect. After a client requests to participate/use the server, there server spawns a worker thread with a server socket on a different (available) port number and tell the client that port number. This is the reserved communication channel for that client with the server.
The rest is pretty straightforward: a client can send a new chat message, the server will pick it up and send it to all connected clients.
If a client disconnects, the worker thread will close the socket, return it to the pool and terminate.

Categories