At this point, I am testing a webserver client/host system to be run on my raspberry pi (host) and on my pc (client). The basic idea is that every 5 seconds, the client on my pc sends a message to the host located at "192.168.0.11" at port 7051. It processes it and sends a message back to my pc.
For this I am using the following client code:
public static String getData() throws Exception {
try {
Socket socket = new Socket(SERVER_ADDRESS, SERVER_PORT);
socket.setReuseAddress(true);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
int msg = 71;
out.write("TEALBEE_CUR:" + msg);
out.flush();
String input;
String data = "";
while ((input = in.readLine()) != null) {
data += input;
}
socket.close();
return data;
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
return null;
}
The problem here is that while data-flow is consistent and can run for at least a week; I lost use of other sockets connections on my pc, namely my Kodi remote control (this is media centre which I can control through a socket connection on my smartphone). My pc at address "192.168.0.37" accepts connections at port 193 for Kodi but after running the Java client for some time and sending a lot of requests to the server, I notice that the remote cannot connect anymore to my PC.
I thought that this might be the case because the sockets cannot be reused and after a single use the socket becomes unusable. This does seem to be the case as my host detects a different socket port for each request.
I tried to solve this by adding the code socket.setReuseAddress(true) and properly closing the socket after each message, but the problem still occurs.
How can I fix this properly (if possible only use one client socket and close this properly so it can be used again the next time).
EDIT: also important to note I can access 192.168.0.37:193 from my PC, but not from my smartphone when the socket connection cannot be established. Yes I am sure that the PC and smartphone and RPI are on the same network and without the client program running I CAN access 192.168.0.37:193 from my smartphone.
Related
I'm trying to build a project where I must pilot an IoT device from smartphone via Wifi.
This device has the SPWF01 Wifi Module integrated, and is configured as an access point (that has no Internet access) with security type WEP. On this access point configuration we also have a TCP Socket Server that intercepts smartphone communications.
On the smartphone side, we have the part which scans and connects to our device's access point(which works, although i get the esclamation point on the wifi icon since it has no Internet access). After we've connected, we start the Client Socket which connects to the server on our IoT device(the ip address of the server socket is actually the gateway of the access point). And here is where the trouble starts, because the client socket won't start. Here is the code:
public void SocketInit(String ip, int port) throws IOException {
InetAddress addr = InetAddress.getByName(ip);
SocketAddress sockaddr = new InetSocketAddress(addr, port);
nsocket = new Socket();
nsocket.setReuseAddress(true);
nsocket.setTcpNoDelay(false);
nsocket.setReceiveBufferSize(700); //Must be less than 730byte witch is the module buffer
nsocket.setSendBufferSize(700);
nsocket.connect(sockaddr, 5000); //5 second connection timeout
}
And here is the exception i get:
java.net.SocketException: socket failed: ENONET (Machine is not on the network)
And I get that error even before reaching nsocket.connect(), precisely on setReuseAddress.
Since the exception I get is ENONET, I thought that it must be because the access point has no internet access so I used the solution proposed here for testing purpose:
adb shell settings put global captive_portal_detection_enabled 0
This is a solution that can't be done programmatically without having root access, but I wanted to test if that was the problem. But although the exclamation mark on the wifi icon had disappeared, the client socket still gave me the same exception error.
Does anybody have a solution for this behaviour? Thank you in advance!
Sometimes the client socket manages to open, with a success rate of 1 out of 20 times. But when it does, i usually get another exception after a couple of messages sent:
java.net.SocketException: recvfrom failed: ECONNRESET (Connection reset by peer)
Here is the code I used to connect to the access point from the smartphone:
WifiConfiguration wc=new WifiConfiguration();
wc.SSID= host;
wc.status = WifiConfiguration.Status.ENABLED;
wc.priority = 40;
wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
wc.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
wc.allowedGroupCiphers.clear();
wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
wc.wepKeys[0] = password;
wc.wepTxKeyIndex = 0;
int netId = mainWifi.addNetwork(wc);
try {
//mainWifi.setWifiEnabled(true);
mainWifi.disconnect();
mainWifi.enableNetwork(netId, true);
mainWifi.reconnect();
startConnectionCheck = true;
System.out.println("enabled network");
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}
The access point's security type is WEP. That is because the Wifi module can't implement WPA.
Tests done on Marshmallow.
I am not 100% certain if this issue is the same.
I had to do a project a whileback and used Java sockets.
When doing intial testing, I used the local loopback and used ports on the same computer and multiple threads. Eventually it worked well enough to test between two computers. I found it didn't work between two computers. After turning off all my firewalls and protections etc on the network and getting desperate enough to use direct connection ethernet cables, I figured out the issue.
Sockets cares which gateway you use. The solution was for me to use the gateway rather than the loopback... It is obvious looking back now...
Anyway, it is likely that your mobile gateway, wifi gateway, and local loopback are all different.
Here is an ugly code blurbe that I hope gives direction with very little inspiration...
Socket socket = null;
try {
socket = new Socket(ip, port, InetAddress.getLoopbackAddress(), localServerPort);
}
catch (Exception e) {
}
if (socket == null) {
try {
socket = new Socket(ip, port, InetAddress.getLocalHost(), localServerPort);
}
catch (Exception e) {
}
}
if(socket == null) {
throw new Exception("Neither the loop back nor the host could find this sucker.");
}
Good Day,
I was taking a look at this tutorial to do a TCP Threadpool server.
http://tutorials.jenkov.com/java-multithreaded-servers/thread-pooled-server.html
It works great for listening/RECEIVING to clients and processing, and returning a response. There is a class inside that I pass in WorkerRunnable into, and that basically prints out the remote socket address (who it was sent from)
public void run(){
synchronized(this){
this.runningThread = Thread.currentThread();
}
openServerSocket();
while(! isStopped()){
Socket clientSocket = null;
try {
clientSocket = this.serverSocket.accept();
} catch (IOException e) {
if(isStopped()) {
System.out.println("Server Stopped.") ;
return;
}
throw new RuntimeException(
"Error accepting client connection", e);
}
this.threadPool.execute(
new WorkerRunnable(clientSocket,
"Thread Pooled Server"));
}
this.threadPool.shutdown();
System.out.println("Server Stopped.") ;
}
The problem is. The remote address is supposed to stay fixed (I am working within my own home wifi router). However, the IP address of the sender stays the same, but the port keeps changing!!
This is a big problem for me..as I need to be able to return a response to the user for future tasks and I actually save this address to use again to send data. When I ran this in a single TCP thread..it stayed fixed (the port).
Why does the threadpool cause the TCP remote address port to keep changing?
With TCP, the client socket port is most of the time (almost 99%, except for specific protocols) randomly chosen. But to you don't have to know it, the only thing you have to do is to keep the clientSocket reference to write back data to the client. If you want to send data to the other host after that the connection is closed, you have to start a ServerSocket on both sides with a fixed port.
Even if you test from same machine the client port will be random by default. I am not sure if there is any way to set the client source port. However, if you use netstat or capture the packet you can be sure the source port is different for every connection.
I would like to create a program that will emulate a device connected to the network and send signals through a specific port.
The device is connected to the network and sends data through a port. On the server(or computer) I have running the CPR Manager v.4.3.0.1 from Lantronix that will associate the IP:PORT to a virtual COM port on the computer. I have a java program that listens to the COM ports and performs an action, this works great with the device.
I tried writing a java app using the Socket class to perform the connection but it was un successful, on the CPR side it only registers a Disconnect when the very first line is executed:
Socket socket = new Socket("192.168.1.160", 8888);
I also tried it using the UDP method and no message whats so ever is recorded.
Any help would be greatly appreciated. Also if there is no possible solution for Java then any other language would do fine.
EDIT:
Here is the Java code where I am attempting to send the data
public static void main(String[] args){
try{
Socket socket = new Socket("192.168.1.160", 8888);
if(socket.isConnected()){
System.out.println("It is connected.");
socket.setKeepAlive(true);
System.out.println(socket.isBound());
}else{
System.out.println("It is not connected.");
}
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String msg = "32";
for(int i = 0; i < 50; i++){
out.println(msg);
}
//Receive a reversed message
msg = in.readLine();
System.out.println("Server : " + msg);
}catch(Exception ioe){
ioe.printStackTrace();
}
}
Thanks.
Update
I got in contact with some people of the devices and they showed me that there is a way to communicate straight via a TCP/IP connection sending there ASCII Command Protocols. This would allow more in depth control at every level.
So, now I am writing a java program that can communicate using these protocols.
Because, I am not using a comm port anymore I am tying to emulate the baud rate, data bits, stop bit stuff. I will post when I have some that works.
Thanks for all the help.
if the product you are using is forwarding the traffic to a COM port should you be listening on the COM port not on a network connection. Sockets are for network traffic. A quick google search resulted this for me.
How to send data to COM PORT using JAVA?
Maybe that will help?
I created a simple echo server in Java. When I try it locally, it works as it should. However, when I try to connect it from a different computer using the IP address and the port number the server is running on, it never connects. Is there anything else that should be done to connect to a server from a different computer?
import java.net.Socket;
import java.net.ServerSocket;
public class EchoServer {
public static void main(String[] args) throws Exception {
// create socket
int port = 4444;
ServerSocket serverSocket = new ServerSocket(port);
System.err.println("Started server on port " + port);
// repeatedly wait for connections, and process
while (true) {
// a "blocking" call which waits until a connection is requested
Socket clientSocket = serverSocket.accept();
System.err.println("Accepted connection from client");
// open up IO streams
In in = new In (clientSocket);
Out out = new Out(clientSocket);
// waits for data and reads it in until connection dies
// readLine() blocks until the server receives a new line from client
String s;
while ((s = in.readLine()) != null) {
out.println(s);
}
// close IO streams, then socket
System.err.println("Closing connection with client");
out.close();
in.close();
clientSocket.close();
}
}
}
Please check the following things.
Is the server computer behind a network proxy ?
Does it have an independent public IP Address by which it is accessible from
anywhere ? Or, does it have an internal IP, by which it can be accessed in your LAN ?
Make sure FireWalls has an exception for port 4444. Or you may turn it of in both client and server.
If it does not help, post the exception you are getting (by editing the question). Or the server program is just freezing without any error ?
If this is on your LAN refer to the machine running your EchoServer by name (the actual machine name, I believe they show you to do it this way on the Sun Tutorial that posted this echo server excercise correct?). If that works it would help a lot in troubleshooting the issue.
I have written a client side java application which communicates through http to a php server. I need to implement a listener on the java (client) side to respond to requests made by the php server. Currently, the java apps are hitting a text file on the server that is updated every minute.
This has worked ok, but now the number of client java apps is rising and this primitive system is starting to break down.
What is the best way to change this? I tried a java ServerSocket listener on the java client app, but can't get that to work. I am having trouble completing the communication. All examples on the web use localhost as ip address example, and my php server is remote hosted.
Do I need to get the ip address of the client machine and send that to the php server so php will know where to send the message? Here is the java code... This is all over the web...
public class MyJavaServer
{
public static void main(String[] args)
{
int port = 4444;
ServerSocket listenSock = null; //the listening server socket
Socket sock = null; //the socket that will actually be used for communication
try
{
System.out.println("listen");
listenSock = new ServerSocket(port);
while (true)
{
sock = listenSock.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
String line = "";
while ((line = br.readLine()) != null)
{
bw.write("PHP said: " + line + "\n");
bw.flush();
}
//Closing streams and the current socket (not the listening socket!)
bw.close();
br.close();
sock.close();
}
}
catch (IOException ex)
{
System.out.println(ex);
}
}
}
... and here is the php
$PORT = 4444; //the port on which we are connecting to the "remote" machine
$HOST = "ip address(not sure here)"; //the ip of the remote machine(of the client java app's computer???
$sock = socket_create(AF_INET, SOCK_STREAM, 0)
or die("error: could not create socket\n");
$succ = socket_connect($sock, $HOST, $PORT)
or die("error: could not connect to host\n");
$text = "Hello, Java!\n"; //the text we want to send to the server
socket_write($sock, $text . "\n", strlen($text) + 1)
or die("error: failed to write to socket\n");
$reply = socket_read($sock, 10000, PHP_NORMAL_READ)
or die("error: failed to read from socket\n");
echo $reply;
This simply does not work. The java app listens, but the php script never connects.
Also, is this the best method for my needs??
Thanks.
The code you include works if the php server machine could connect to the java client machine. In your case that this is all over the web, it means that the java client machine should have an IP that are accessible to public. Once you have it, assign that IP to $HOST, then the code will runs fine.
Assuming that no client can have a public IP, I think the best method is to make your java client talk to your PHP Server in request-reply manner using HTTP request. The java client, acting like a web browser, send a HTTP request and receive HTTP reply that contains data needed by your java client. And when the client numbers rise to a level that you PHP server cannot handle, you could scale it up. Although I haven't had the experience myself, scaling up a PHP server is not uncommon these days.