I am trying to get into IoT and want to make an app send a string from an android phone to a Linux pc. The app does this by implementing an asynctask:
//From the java docs, slightly modified
private Void sendThroughSocket(String s, String host, int port) {
Log.d("E", "In send through socket");
final String hostName = host;//Host is the address of the receiver, can be IP or domain
int portNumber = port;
//Check if device is connected to internet
try {
Socket clientsocket = new Socket(hostName, portNumber); //one of 2-way point communication
Log.d("E", "Created Socket: ");
DataOutputStream DOS = new DataOutputStream(clientsocket.getOutputStream());
if (clientsocket.isConnected())
Log.d("E", "Socket connected");
DOS.writeUTF(s);
clientsocket.close();
} catch (UnknownHostException e) {
System.err.println("Don't know about host " + hostName);
new Runnable() {
public void run() {
Toast.makeText(context, "Don't know about host " + hostName, Toast.LENGTH_SHORT).show();
}
};
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to " + hostName);
//Toast can not be run using asynctask since it acesses UI
new Runnable() {
public void run() {
Toast.makeText(context, "Couldn't get I/O for the connection to " + hostName + " , check the port", Toast.LENGTH_SHORT).show();
}
};
} catch (Exception e) {
Log.d("E", "#fares" + e.getClass().getName().toString());
}
return null;
}
On 3 occasions do I try to send the string, all triggered from my seekbar (I send the seek bar progress value as my string):
public void onProgressChanged(SeekBar seekBar, int i, boolean b)
public void onStartTrackingTouch(SeekBar seekBar)
public void onStopTrackingTouch(SeekBar seekBar)
The implementation for all 3 is the same:
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
progressvalue = i;
textView.setText("Brightness = " + progressvalue + " %");
if (((RecieverPort.equals("Please enter port Number")) || (RecieverIP.equals("Please enter receiver IP")))) {
//Make sure toast isn't persistent
if (IPPortToastcount++ == 0)
Toast.makeText(MainActivity.this, "Please set both IP and Port ", Toast.LENGTH_SHORT).show();
} else {
//Check if connected to internet
if (!isConnectedtoInternet(MainActivity.this)) {
if (ConnectivityToastCount++ < 1)
Toast.makeText(MainActivity.this, "You are not connected to the Internet", Toast.LENGTH_SHORT).show();
} else {
//Send text over wifi
SendText ST = new SendText(getApplicationContext());
ST.execute(String.valueOf(progressvalue), RecieverIP, RecieverPort);
ST.cancel(false);
}
}
}
Mainly
//Send text over wifi
SendText ST = new SendText(getApplicationContext());
ST.execute(String.valueOf(progressvalue), RecieverIP, RecieverPort);
ST.cancel(false);
The server side (my pc) is pretty simple:
int portNumber = 44339; // Choose unused port on router
//Open a socket
try {
//System.out.println("in try statement");
try (ServerSocket serverSocket1 = new ServerSocket(portNumber)) {
portNumber = serverSocket1.getLocalPort();
System.out.println("Created socket at port " + portNumber);
Socket clientSocket = serverSocket1.accept();
System.out.println("Accepted");
DataInputStream DIS = new DataInputStream(clientSocket.getInputStream()); //get input from socket
//System.out.println("Created reader");
String inputLine;
// System.out.println("About to read");
while (DIS.available() > 0) {
inputLine = DIS.readUTF();
System.out.println(inputLine);
}
}
} catch (Exception e) {
System.out.println("Exception caught when trying to listen on port "
+ portNumber + " or listening for a connection");
System.out.println(e.getClass().getSimpleName());
}
This kind of works, except it takes a very long time(seconds) before the server socket is accepted. It also only works in onprogresschanged , which leads me to believe that multiple attempts of
//Send text over wifi
SendText ST = new SendText(getApplicationContext());
ST.execute(String.valueOf(progressvalue), RecieverIP, RecieverPort);
ST.cancel(false);
are needed before one succeeds at creating the socket and connecting to the pc. How can I make sure that one tap, or one call of the function will be enough to send the string?
Sorry for the long post but it's my first time asking :)
Edit: my new server code:
try {
//System.out.println("in try statement");
try ( ServerSocket serverSocket1 = new ServerSocket(portNumber))
{
portNumber = serverSocket1.getLocalPort();
System.out.println("Created socket at port " + portNumber);
while(true){
Socket clientSocket = serverSocket1.accept();
// System.out.println("Accepted");
DataInputStream DIS = new DataInputStream(clientSocket.getInputStream()); //get input from socket
//System.out.println("Created reader");
//String inputLine;
//System.out.println("About to read");
System.out.println(DIS.readUTF());
}
}
} catch (Exception e) {
System.out.println("Exception caught when trying to listen on port "
+ portNumber + " or listening for a connection");
System.out.println(e.getClass().getSimpleName());
}
Worth noting that even in the while true loop, the server will always display 4 numbers then stop.
Edit: here is an example log:
10-06 20:08:09.145 26372-26372/com.example.fares.ledslider D/E: #fares in test method value = 50
10-06 20:08:26.475 26372-26372/com.example.fares.ledslider D/E: #Fares in start tracking
10-06 20:08:26.722 26372-27004/com.example.fares.ledslider D/E: #fares Socket connected
10-06 20:08:26.810 26372-26764/com.example.fares.ledslider D/E: #fares Socket connected
10-06 20:08:27.241 26372-27003/com.example.fares.ledslider D/E: #fares Socket connected
10-06 20:08:27.304 26372-26372/com.example.fares.ledslider D/E: #fares in stop tracking
ST.cancel() can be removed. Also not waiting for availability looks not good.
Related
Below code hangs does not go past beyond below messages and is hanging at socket.accept().
Its part of an android app and INTERNET permissions are already added to manifest. Tried putting accept in while(true) loop...but that did not work:
09-23 15:55:43.737 24079-25436: Trying to open port 5556...
09-23 15:55:43.739 24079-25436: >>> Opening Port : 5556
private Socket socket = null;
private ServerSocket server = null;
private static final String TAG = "MyActivity";
public boolean openPort(String host , int port){
try {
server = new ServerSocket(port);
} catch (IOException e) {
Log.e(TAG , "Error initializing serverSocket: " , e);
}
Log.e(TAG , ">>> Opening Port : " + port);
boolean bmsg = false;
try {
socket = server.accept();
Log.e(TAG , ">>> Opened Port : " + port);
return true;
} catch(IOException e){
Log.e(TAG, "Error opening port: ", e);
return bmsg;
} catch(SecurityException s){
Log.e(TAG, "sError opening port: ", s);
return bmsg;
} catch(IllegalBlockingModeException b){
Log.e(TAG, "bError opening port: ", b);
return bmsg;
}
}
Above class is being called from below async task on button click:
private class openPort extends AsyncTask{
#Override
protected Object doInBackground(Object[] objects) {
Log.i(TAG , "Trying to open port 5556...");
//host is localhost
//port is 5556
OpenClosePort ocp = new OpenClosePort();
ocp.openPort(host , port);
return null;
}
}
I am trying to etablish a connection to a monero mining pool. I know that the mining pools using the stratum protocol. But the only thing I receive is a connection timeout if I try to create a socket:
try{
InetAddress address = InetAddress.getByName("pool.supportxmr.com");
Log.d("miner","Attempting to connect to " + address.toString() + " on port " + port + ".");
Socket socket = new Socket(address, 3333);
Log.d("miner", "Connection success");
}catch (IOException e){
e.printStackTrace();
}
SupportXmr is just an example. Its not working with any pool. What am I doing wrong?
Try with port 80. Make sure you wrote INTERNET permission to AndroidManifest and use AsnycTask.
private class AsyncExec extends AsyncTask<Void,Void,Void>{
#Override
protected Void doInBackground(Void... voids) {
int port=80;
try
{
InetAddress address = InetAddress.getByName("pool.supportxmr.com");
Log.d("miner","Attempting to connect to " + address.toString() + " on port " + port + ".");
Socket socket = new Socket(address, 3333);
Log.d("miner", "Connection success");
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
}
}
- Also don't forget to call new AsyncExec().execute().
I'm trying to write simple server-client chat solution. For test purposes, I'm creating an array of 2 serverThreads, which are responsible for sending and receiving messages from the clients connected.
I'd like a server to reject a connections after the number of connected clients reach a maximum value. However, even though the server do not accept the connection, the socket on client side is created. Methods socket.isBound and isConnected both return true value.
So back to the main question. Do you have any ideas how could I reject the client from connecting when the ServerSocket will not be able to .accept() additional connection?
Here's the code of the Server class.
public class Server {
private ServerSocket serverSocket = null;
private ServerThread serverThread[] = new ServerThread[2];
protected volatile int clientCount = 0;
public Server (int port){
try {
System.out.println("Binding to port " + port + " ...");
serverSocket = new ServerSocket (port);
System.out.println("Binded to port " + port + ".");
} catch (IOException e) {
System.out.println("Failed binding to the port: " + e.getMessage());
}
}
public void addThread (Socket socket){
System.out.println ("Client connected at socket: " + socket);
serverThread[clientCount] = new ServerThread (this, socket);
try {
serverThread[clientCount].open();
serverThread[clientCount].start();
} catch (IOException e) {e.getMessage();}
}
public void waitForClient () {
boolean isLogPrinted = false;
while (true){
try {
if (clientCount < serverThread.length){
System.out.println ("Waiting for connection...");
isLogPrinted = false;
addThread (serverSocket.accept());
clientCount++;
System.out.println("Client count: " + clientCount);
}
else {
if (!isLogPrinted){
System.out.println("MAXIMUM NUMBER OF CLIENTS REACHED! (" + clientCount + ").");
isLogPrinted = true;
}
}
} catch (IOException e) {
System.out.println("Error while waiting for new clients to connect: " + e.getMessage());
}
}
}
public synchronized void broadcastMessages (String msg){
for (int i = 0; i < clientCount; i++)
serverThread[i].sendMessage(msg);
}
public static void main (String args[]){
Server server = new Server (4200);
server.waitForClient();
}
}
I'd like a server to reject a connections after the number of connected clients reach a maximum value.
Close the server socket.
However, even though the server do not accept the connection, the socket on client side is created. Methods socket.isBound and isConnected both return true value.
Correct. That's because TCP maintains a 'backlog queue' of incoming connections which have been completed but not yet accepted by the server application.
So back to the main question. Do you have any ideas how could I reject the client from connecting when the ServerSocket will not be able to .accept() additional connection?
Close the server socket while the number of connections is at its maximum.
However due to the backlog this technique can never be perfect. There is no perfect solution. You could have the server immediately close excess connections, but the excess clients won't detect that until they try to send something. If you need perfection you will probably have to introduce an application protocol whereby the server sends something like 'ACCEPTED' or 'REJECTED' accordingly.
Instead of while true in you waitForClient method try this
private final int allowedClients = 10;
private int connectedClients = 0;
public void waitForClient () {
boolean isLogPrinted = false;
while (connectedClients <= allowedClients){
try {
if (clientCount < serverThread.length){
System.out.println ("Waiting for connection...");
isLogPrinted = false;
addThread (serverSocket.accept());
connectedClients++;
System.out.println("Client count: " + clientCount);
}
else {
if (!isLogPrinted){
System.out.println("MAXIMUM NUMBER OF CLIENTS REACHED! (" + clientCount + ").");
isLogPrinted = true;
}
}
} catch (IOException e) {
System.out.println("Error while waiting for new clients to connect: " + e.getMessage());
}
}
}
I know this is very late to answer, but I think it will help many.
You can check for the existing socket if any by below code.
SocketAddress socketAddress = new InetSocketAddress("localhost", 8091);
Socket socket = new Socket();
ServerSocket serverSocket = null;
try {
socket.connect(socketAddress);
} catch (IOException e) {
e.printStackTrace();
}
if(socket == null) {
try {
serverSocket = new ServerSocket(8091);
} catch (IOException e) {
e.printStackTrace();
}
}
if not found a active socket on the same port and IP then it will start a new server socket or you can change it start socket only else you can connect to the existing socket.
I will post my code below, a little background.
I am trying to connect to a gameserver on port 9339. my local port changes each time. The aim is to pass the packets through the proxy and display the info in the command line.
The client connects to the remote host using bluestacks which is running the game.
Code:
import java.io.*;
import java.net.*;
public class proxy {
public static void main(String[] args) throws IOException {
try {
String host = "gamea.clashofclans.com";
int remoteport = 9339;
ServerSocket ss = new ServerSocket(0);
int localport = ss.getLocalPort();
ss.setReuseAddress(true);
// Print a start-up message
System.out.println("Starting proxy for " + host + ":" + remoteport
+ " on port " + localport);
// And start running the server
runServer(host, remoteport, localport,ss); // never returns
System.out.println("Started proxy!");
} catch (Exception e) {
System.err.println(e);
}
}
/**
* runs a single-threaded proxy server on
* the specified local port. It never returns.
*/
public static void runServer(String host, int remoteport, int localport, ServerSocket ss)
throws IOException {
final byte[] request = new byte[2048];
byte[] reply = new byte[4096];
while (true) {
Socket client = null, server = null;
try {
// Wait for a connection on the local port
client = ss.accept();
System.out.println("Client Accepted!");
final InputStream streamFromClient = client.getInputStream();
final OutputStream streamToClient = client.getOutputStream();
// Make a connection to the real server.
// If we cannot connect to the server, send an error to the
// client, disconnect, and continue waiting for connections.
try {
server = new Socket(host, remoteport);
System.out.println("Client connected to server.");
} catch (IOException e) {
PrintWriter out = new PrintWriter(streamToClient);
out.print("Proxy server cannot connect to " + host + ":"
+ remoteport + ":\n" + e + "\n");
out.flush();
client.close();
System.out.println("Client disconnected");
continue;
}
// Get server streams.
final InputStream streamFromServer = server.getInputStream();
final OutputStream streamToServer = server.getOutputStream();
// a thread to read the client's requests and pass them
// to the server. A separate thread for asynchronous.
Thread t = new Thread() {
public void run() {
int bytesRead;
try {
while ((bytesRead = streamFromClient.read(request)) != -1) {
streamToServer.write(request, 0, bytesRead);
streamToServer.flush();
}
} catch (IOException e) {
}
// the client closed the connection to us, so close our
// connection to the server.
try {
streamToServer.close();
} catch (IOException e) {
}
}
};
// Start the client-to-server request thread running
t.start();
// Read the server's responses
// and pass them back to the client.
int bytesRead;
try {
while ((bytesRead = streamFromServer.read(reply)) != -1) {
streamToClient.write(reply, 0, bytesRead);
streamToClient.flush();
}
} catch (IOException e) {
}
// The server closed its connection to us, so we close our
// connection to our client.
streamToClient.close();
} catch (IOException e) {
System.err.println(e);
} finally {
try {
if (server != null)
server.close();
if (client != null)
client.close();
} catch (IOException e) {
}
}
}
}
}
Basically the last thing that is printed out is "Starting proxy for gamea.clashofclans.com:9339 on port (whatever it chose).
Hopefully someone can help me.
I have this problem too, I don`t have enough time to correct this but i think using thread is that is why all mistake.
check your proxy for working on browser setting( May be proxy had problem)
If not,
I suggest to don`t use thread. maybe mutual exclusion occurs.
Your code is correct.It is working fine so you don't need any fix. What is happening is , your serverSocket in your proxy class is waiting for client to connect. that's why it is not going forward. What you need to do is, create a client and connect to it.
follow the step :
run your proxy.
then run your client
for the client, you can use this code,
public static void main(String[] args) throws IOException {
try {
int remoteport = 9339;
String host="127.0.0.1";
makeConnection(host, remoteport);
System.out.println("connection successful!");
} catch (Exception e) {
System.err.println(e);
}
}
public static void makeConnection(String host, int remoteport) throws IOException {
while (true) {
Socket client = null;
try {
client = new Socket(host, remoteport);
System.out.println("Client connected to server.");
break;
} catch (IOException e) {
System.err.println(e);
} finally {
if (client != null)
client.close();
if (client != null)
client.close();
}
}
}
I have this client class "T_Client" in a client-server implementation
T_Client:
public class T_Client{
private static final String TAG = "T_Client";
private static String serverIP = "192.168.2.5";
private static int port = 4444;
private InetAddress serverAddr = null;
private Socket sock = null;
private boolean running = false;
private ObjectInputStream in;
private ObjectOutputStream out;
Object objIn;
public void send(MessageCustom _msg) {
if (out != null) {
try {
out.writeObject(_msg);
out.flush();
// out.close();
Log.i("Send Method", "Outgoing : " + _msg.toString());
} catch (IOException ex) {
Log.e("Send Method", ex.toString());
}
}
}
public void stopClient() {
running = false;
}
public void run() {
running = true;
try {
// here you must put your computer's IP address.
serverAddr = InetAddress.getByName(serverIP);
Log.i("TCP Client", "C: Connecting...");
// create a socket to make the connection with the server
sock = new Socket(serverAddr, port);
try {
// send the message to the server
out = new ObjectOutputStream(sock.getOutputStream());
// receive the message which the server sends back
in = new ObjectInputStream(sock.getInputStream());
Log.i("TCP Client", "C: Connected.");
// in this while the client listens for the messages sent by the
// server
while (running) {
objIn = in.readObject();
Log.i("Object Read", objIn.toString());
}
Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + objIn
+ "'");
} catch (Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
// the socket must be closed. It is not possible to reconnect to
// this socket
// after it is closed, which means a new socket instance has to
// be created.
out.close();
in.close();
sock.close();
Log.i(TAG, "Closing socket: " + sock);
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
}
}
}
And I want to get the Object from the server(objIn) and pass it to the UI thread so I can do some UI updates there. From searching around a bit, I think that I have to use a Handler, but can't really wrap my head around the implementation.
Could someone give me a simple example of how to implement a handler in my case, and make the call in a Main Activity? Or point me to a simple tutorial to get me started, cause I've tried to follow the one over at the Android Developers site but it's too complicated.