My android app connects the server with TCP socket, to make sure the connection is ok, the server sends the "keep-alive" msg every 10s when idle, I can grab the packet in WireShark, but in my app, I can't handle the packet anywhere, seems that the packet can't be read with the socket.
Below is the code segment of my socket connection. Seems that the "keep-alive" packet just can't be read with the inputstream...
public class SocketBase {
private Socket mSocket;
private DataOutputStream out;
private DataInputStream in;
private SocketCallback callback;
private int timeOut = 1000 * 30;
public SocketBase(SocketCallback callback) {
this.callback = callback;
}
public void connect(String ip, int port) throws Exception {
mSocket = new Socket();
SocketAddress address = new InetSocketAddress(ip, port);
mSocket.connect(address, timeOut);
if (mSocket.isConnected()) {
out = new DataOutputStream(mSocket.getOutputStream());
in = new DataInputStream(mSocket.getInputStream());
callback.connected();
}
}
public void write(byte[] buffer) throws IOException {
if (out != null) {
out.write(buffer);
out.flush();
}
}
public void disconnect() {
try {
if (mSocket != null) {
if (!mSocket.isInputShutdown()) {
mSocket.shutdownInput();
}
if (!mSocket.isOutputShutdown()) {
mSocket.shutdownOutput();
}
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
mSocket.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
callback.disconnect();
out = null;
in = null;
mSocket = null;
}
}
public void read() throws IOException {
if (in != null) {
byte[] buffer = new byte[1024*1];
byte[] tmpBuffer;
int len = 0;
Log.i("SOCKET", "something comming");
while ((len = in.read(buffer)) > 0) {
tmpBuffer = new byte[len];
System.arraycopy(buffer, 0, tmpBuffer, 0, len);
callback.receive(tmpBuffer);
tmpBuffer = null;
}
}
}
}
The "keep-alive" packet in WireShark is like this:
If you mean a regular TCP keep-alive, there's nothing for you to detect or do. Your TCP implementation takes care of acknowledging it. There's no application data in it, so there's nothing for you to read.
Related
Is there any good option to send broadcast message on UDP port while receiving data from other devices on the same port?
I have this currently:
First I initialize 1 DiagramSocket for both reading and sending:
private void startSocket(){
try {
if(socket == null) {
socket = new DatagramSocket(3040);
socket.setBroadcast(true);
socket.setReuseAddress(true);
}
} catch (Exception e) {
e.printStackTrace();
}
}
In first Thread I have reading/receiving for current socket:
public class Server implements Runnable {
public Server(iBroadcastResponse iBResponse){
BroadcastClass.this.iBResponse = iBResponse;
}
#Override
public void run() {
startSocket();
while (DataHandler.isEmergencyMode.get() ) {
try {
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
if(socket == null)
return;
socket.receive(packet);
String command = stringFromPacket(packet);
Log.d(TAG, command);
addToBroadcastCalls(command);
if(iBResponse != null)
iBResponse.onResponse();
} catch (Exception e) {
Log.e(TAG, "Server: Error!\n");
}
}
Log.e(TAG, "Stop!");
}
String stringFromPacket(DatagramPacket packet) {
return new String(packet.getData(), 0, packet.getLength());
}
}
If I run this, it works normally, reads receiving data. But if I try to send data in another thread:
socketThread = new Thread(){
#Override
public void run() {
startSocket();
String message = "Message";
byte[] buf = message.getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length);
try {
if(!socket.isConnected())
socket.connect(InetAddress.getByName("255.255.255.255"), 3040);
if (socket != null) {
socket.send(packet);
}
Log.d(TAG, "Send: " +message);
} catch (Exception e) {
e.printStackTrace();
}
}
};
socketThread.start();
When .send() is called it stops receiving data from other devices so now it only send message but stops receiving it from other devices.
Is there any good solution to this problem?
This was the solution
https://stackoverflow.com/a/25520279/1088975
I only changed
System.log...
To
Log.w(TAG, "Message...");
And I changed IP to be always "255.255.255.255" instead of
getBroadcastAddress()
which returns broadcast IP for current WIFI, which didn't work on my android devices
I have an android app that I would like to make it be able compare data via wi-fi p2p.
I understand the connection method (1. Set up app. permissions; set up broadcast reciever and P2P manager; initiate peer descovery; connect to peer)
But I have a problem when it comes to data transfer. My app's interface has some drop-down menus
with several options to select from. I was wondering, how can I make the selected options (once the app users connect to each other)
be able to compare data and notify the app users if they have mutual selections.
Will this code work?
//SERVER
public static class FileServerAsyncTask extends AsyncTask {
private Context context;
private TextView statusText;
public FileServerAsyncTask(Context context, View statusText) {
this.context = context;
this.statusText = (TextView) statusText;
}
#Override
protected String doInBackground(Void... params) {
try {
/**
* Create a server socket and wait for client connections. This
* call blocks until a connection is accepted from a client
*/
ServerSocket serverSocket = new ServerSocket(8888);
Socket client = serverSocket.accept();
/**
* If this code is reached, a client has connected and transferred data
*/
var pGender:String
var pDesire:String
var pAge:String
var pRace:String
var pWeight:String
var pHeight:String
var dGender:String = dGender.getValue(dGender.selectedItem.data);
var pDesire:String = pDesire.getValue(pDesire.selectedItem.data);
var dRace:String = dRace.getValue(dRace.selectedItem.data);
var dAge:String = dAge.getValue(dAge.selectedItem.data);
var dHeight:String = dHeight.getValue(dHeight.selectedItem.data);
var dWeight:String = dWeight.getValue(dWeight.selectedItem.data);
if (pGender == dGender.selectedItem.data && pDesire == pDesire.selectedItem.data && pRace == dRace.selectedItem.data && pWeight == dWeight.selectedItem.data && pHeight == dHeight.selectedItem.data)
{
trace (jump to frame 110 + vibrate);
}
else
{
trace (jump to frame 138 + vibrate + jump to frame 10) ;
}
return results;
}
InputStream inputstream = client.getInputStream();
copyFile(inputstream, new FileOutputStream(f));
serverSocket.close();
return f.getAbsolutePath();
} catch (IOException e) {
Log.e(WiFiDirectActivity.TAG, e.getMessage());
return null;
}
}
/**
* Start activity that can handle the JPEG image
*/
#Override
protected void onPostExecute(String result) {
if (result != null) {
statusText.setText("File copied - " + result);
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file://" + result), "image/*");
context.startActivity(intent);
}
}
}
Then the on the client I have this:
//CLIENT
Context context = this.getApplicationContext();
String host;
int port;
int len;
Socket socket = new Socket();
byte buf[] = new byte[1024];
...
try {
/**
* Create a client socket with the host,
* port, and timeout information.
*/
socket.bind(null);
socket.connect((new InetSocketAddress(host, port)), 500);
/**
* Create a byte stream from a JPEG file and pipe it to the output stream
* of the socket. This data will be retrieved by the server device.
*/
OutputStream outputStream = socket.getOutputStream();
ContentResolver cr = context.getContentResolver();
InputStream inputStream = null;
/*varibles declaration
*/
pGender.getValue(pGender.selectedItem.data);
pDesire.getValue(pDesire.selectedItem.data);
pRace.getValue(pRace.selectedItem.data);
pAge.getValue(pAge.selectedItem.data);
pHeight.getValue(pHeight.selectedItem.data);
pWeight.getValue(pWeight.selectedItem.data);
inputStream = cr.openInputStream(Uri.parse(DataProvider.getItemAt(pGender:String, pDesire:String, pRace:String, pAge:String, pHeight:String, pWeight:String):Object));
while ((len = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, len);
}
outputStream.close();
inputStream.close();
} catch (FileNotFoundException e) {
//catch logic
} catch (IOException e) {
//catch logic
}
/**
* Clean up any open sockets when done
* transferring or if an exception occurred.
*/
finally {
if (socket != null) {
if (socket.isConnected()) {
try {
socket.close();
} catch (IOException e) {
//catch logic
}
}
}
}
I am developing a android wifi -chat application .
Bit of Info about my app :
->A device calls startserver() to act as a server ,another device calls start client() to act as a client
What works:
->A Client can successfully send the data for the first time to the client, but not again and again
->I need to call startserver() again on first device , so that client can send data again .
The startserver() calls this Async task ,the following is its DoinBackgroundMethod
protected String doInBackground(Void... params) {
ServerSocket serverSocket = null;
try {
while(true) {
serverSocket = new ServerSocket(PORT);
Socket client = serverSocket.accept();
StartMSG(client);
}
} catch (IOException e) {
return null;
} finally {
try {
chatclient.changeserverrunning(false);
if (serverSocket == null) {
} else {
serverSocket.close();
}
return null;
} catch (Exception e) {
}
}
//return null;
}
protected void StartMSG(Socket client){
try {
InputStream inputstream = client.getInputStream();
ObjectInputStream ois = new ObjectInputStream(inputstream);
Message m = null;
try {
m = (Message) ois.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (m != null) {
if (m.gettype() == 1) {
final String my_msg = m.getMessage();//Toast msg afterwards
}
}catch (Exception e){
}
}
Client Side Code :
It is started when the client hits send button and calls start client method .in which It sets up the Ip values before and bundles them and calls the message sending part as a Intent Service called FileTransferService
Its code is (abstracted) :
protected void onHandleIntent(Intent intent) {
Context context = getApplicationContext();
if(socket==null){
socket = new Socket();
}
if (intent.getAction().equals(ACTION_SEND_FILE)) {
final String msg_type=intent.getExtras().getString(MESSAGE_TYPE);
String host = intent.getExtras().getString(EXTRAS_ADDRESS);
int port = intent.getExtras().getInt(EXTRAS_PORT);
try {
socket.bind(null);
socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);
Message m = (Message) intent.getExtras().getSerializable(MESSAGE_INTENT_STR);
final String my_message=m.getMessage();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(m);
oos.flush();
oos.close();
InputStream is = new ByteArrayInputStream(baos.toByteArray());
OutputStream stream = socket.getOutputStream();
ChatClient.copyFile(is, stream);
} catch (IOException e) {
} finally {
if (socket != null) {
if (socket.isConnected()) {
try {
//socket.close();
} catch (Exception e) {
// Give up
e.printStackTrace();
}
}
}
}
}
}
You should try https://github.com/tavendo/AutobahnAndroid and run the client from a service, from an asyntask it will always end up finishing.
I am trying to sending and receiving data between two mobile phones. Right now I can send data from one device (device 1) to another (device 2), however, when I am reading data in the same device (device 1) I am getting following error:
java.net.SocketException: Socket is closed
I am using the following code to read data:
SocketServerReadThread socketServerReadThread = new SocketServerReadThread(socket);
socketServerReadThread.run();
private class SocketServerReadThread extends Thread {
private Socket mySocket;
SocketServerReadThread(Socket socket) {
mySocket = socket;
}
#Override
public void run() {
try {
inputStream = mySocket.getInputStream();
byte[] buffer = new byte[1024];
byteArrayOutputStream = new ByteArrayOutputStream(1024);
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1){
byteArrayOutputStream.write(buffer, 0, bytesRead);
response += byteArrayOutputStream.toString("UTF-8");
}
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
msgRead.setText(" Response: "+response);
}
});
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
message += "Read Something wrong! " + e1.toString() + "\n";
}
}
}
I would appreciate if anyone could help me to solve the problem.
private class SocketServerReadThread extends Thread {
private Socket mySocket;
SocketServerReadThread(Socket socket) {
this.mySocket = socket;
}
BufferedReader input;
input = new BufferedReader(new InputStreamReader(
this.mySocket.getInputStream()));
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
String read = input.readLine();
System.out.printf("Message read is -> %s%n", read);
if (read != null) {
msgRead.setText(" Response: "+response);
}
}catch(Exception e){}}}}
i am new to android and need simple http connection codes for client server(local server in the network) communication in android application.the connection starts when the application is started and if there is any update in the server it should be notified on the client and the server response must be based on the client request.
please help.
thanks
Socket socket;
InputStream is;
OutputStream os;
String hostname;
int port;
public void connect() throws IOException {
socket = new Socket(hostname, port);
is = socket.getInputStream();
os = socket.getOutputStream();
}
public void send(String data) throws IOException {
if(socket != null && socket.isConnected()) {
os.write(data.getBytes());
os.flush();
}
}
public String read() throws IOException {
String rtn = null;
int ret;
byte buf[] = new byte[512];
while((ret = is.read(buf)) != -1) {
rtn += new String(buf, 0, ret, "UTF-8");
}
return rtn;
}
public void disconnect() throws IOException {
try {
is.close();
os.close();
socket.close();
} finally {
is = null;
os = null;
socket = null;
}
}
connect, send, read, disconnect :)