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){}}}}
Related
I am done with connecting the Bluetooth to a paired device. After establishing the connection I want to move to the next activity, where the data to be sent are given by the user. so the main thing is, how can I send a string to an already connected Bluetooth device(from previous activity). Need help. I searched a lot. Couldn't find it.
Thanks in advance
BluetoothConnectingActivity
private Runnable serverListener = new Runnable() {
public void run() {
try //opening of BT connection
{
//problematic with older phones... HELP: Change server/client orientation...
//but solves: BluetoothAdapter: getBluetoothService() called with no BluetoothManagerCallback
Log.i("TrackingFlow", "Server socket: new way used...");
socket = (BluetoothSocket) remoteDevice.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(remoteDevice, 1);
socket.connect();
CONNECTION_ENSTABLISHED = true; //protect from failing
} catch (Exception e) //obsolete way how to open BT
{
try {
Log.e("TrackingFlow", "Server socket: old way used...");
BluetoothServerSocket tmpsocket = adapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
socket = tmpsocket.accept();
CONNECTION_ENSTABLISHED = true; //protect from failing
Log.i("TrackingFlow", "Listening...");
} catch (Exception ie) {
Log.e(TAG, "Socket's accept method failed", ie);
ie.printStackTrace();
}
}
Log.i(TAG, "Server is ready for listening...");
runOnUiThread(new Runnable() {
#Override
public void run() { //Show message on UIThread
listItems.clear(); //remove chat history
listItems.add(0, String.format(" Server opened! Waiting for clients..."));
listAdapter.notifyDataSetChanged();
}
});
try //reading part
{
is = socket.getInputStream();
os = socket.getOutputStream();
new Thread(writter).start();
int bufferSize = 1024;
int bytesRead = -1;
byte[] buffer = new byte[bufferSize];
while (CONTINUE_READ_WRITE) //Keep reading the messages while connection is open...
{
final StringBuilder sb = new StringBuilder();
bytesRead = is.read(buffer);
if (bytesRead != -1) {
String result = "";
while ((bytesRead == bufferSize) && (buffer[bufferSize - 1] != 0)) {
result = result + new String(buffer, 0, bytesRead - 1);
bytesRead = is.read(buffer);
}
result = result + new String(buffer, 0, bytesRead - 1);
sb.append(result);
}
Log.e("TrackingFlow", "Read: " + sb.toString());
runOnUiThread(new Runnable() {
#Override
public void run() { //Show message on UIThread
Toast.makeText(ConnectToBluetoothActivity.this, sb.toString(), Toast.LENGTH_SHORT).show();
listItems.add(0, String.format("< %s", sb.toString())); //showing in history
listAdapter.notifyDataSetChanged();
}
});
}
} catch (IOException e) {
Log.e(TAG, "Server not connected...");
e.printStackTrace();
}
}
};
StringSendingActivity
public void sendString(String convertedString) { //send converted string
byte[] b = convertedString.getBytes();
try {
Toast.makeText(this, "Sending" + convertedString, Toast.LENGTH_SHORT).show();
os.write(b);
// list.add(0, "> " + et.getText().toString()); //chat history
list.add(0, et.getText().toString()); //chat history
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(getApplicationContext(), R.layout.message_textview, R.id.textview, list);
listview.setAdapter(adapter);
adapter.notifyDataSetChanged();
et.setText(""); //remove text after sending
} catch (IOException e) {
Toast.makeText(getApplicationContext(), "Not sent", Toast.LENGTH_SHORT).show(); //usually problem server-client decision
}
}
I have implemented Socket for a multiplayer game using libGdx.
Client side
private void startClient(String ip, int port) {
SocketHints socketHints = new SocketHints();
// Socket will time our in 4 seconds
socketHints.connectTimeout = 4000;
//create the socket and connect to the server entered in the text box ( x.x.x.x format ) on port 9021
Socket socket = Gdx.net.newClientSocket(Net.Protocol.TCP, ip, port,
socketHints);
try {
System.out.println("JoinScreen.startClient");
// write our entered message to the stream
OutputStream out = socket.getOutputStream();
out.write("testtest shine \n".getBytes());
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
Server code
private void startThreadServer() {
new Thread(new Runnable() {
#Override
public void run() {
System.out.println("HotspotHomeScreen.run");
ServerSocketHints serverSocketHint = new ServerSocketHints();
serverSocketHint.acceptTimeout = 0;
ServerSocket serverSocket = Gdx.net.newServerSocket(Net.Protocol.TCP, mPort, serverSocketHint);
String messageStr = null;
while (true) {
// Create a socket
Socket socket = serverSocket.accept(null);
System.out.println("while true");
int value = 0;
BufferedReader buffer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
try {
while ((value = buffer.read()) != -1) {
char c = (char) value;
if (value != 0 && value != 155)
messageStr = messageStr + c;
// Read to the next newline (\n) and display that text on labelMessage
System.out.println("HotspotHomeScreen.run " + buffer.readLine());
System.out.println("test messageStr = " + messageStr);
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("testnjnihg test" + messageStr);
System.out.println("HostScreen last line");
}
}
}).start(); // And, start the thread running
}
The BufferedReader is invoked after starting the server on one device,but data cannot read. When I switch to debug mode, after reaching while ((value = buffer.read()) != -1) { the buffer shows all the data I sent in the debugger console,but the execution stops there. Sorry for my bad Language
The code is supposed to connect as a client to a TCP server, send a command and receive a response.
The code connects and sends the command but time-out-s at "socket.getInputStream()", even though the connected server receives the command and is supposed to respond (was checked using a TCP client program on the PC).
Here Is the Code for the task:
public class MyClientTask extends AsyncTask<Void, Void, Void> {
String dstAddress;
int dstPort;
String command;
String response = "";
MyClientTask(String addr, int port, String cmd){
dstAddress = addr;
dstPort = port;
command = cmd;
}
#Override
protected Void doInBackground(Void... arg0) {
Socket socket = null;
InputStream inputStream;
try {
socket = new Socket();
socket.connect(new InetSocketAddress(dstAddress, dstPort),2000);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int bytesRead;
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
out.println(command);
inputStream = socket.getInputStream();
socket.setSoTimeout(20000);
while ((bytesRead = inputStream.read(buffer)) != -1){
byteArrayOutputStream.write(buffer, 0, bytesRead);
response += byteArrayOutputStream.toString("UTF-8");
}
}catch (UnknownHostException e){
e.printStackTrace();
response = "UnknownHostException: " + e.toString();
} catch (IOException e) {
e.printStackTrace();
response = "IOException: " + e.toString();
} catch (Throwable e) {
e.printStackTrace();
response = "Throwable: " + e.toString();
}finally{
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(Void result) {
textResponse.setText(response);
super.onPostExecute(result);
}
}//MyClientTask
You're reading the response until end of stream. End of stream won't occur until the peer closes the connection. You got a read timeout: ergo, probably, he didn't close the connection. Or else your timeout is too short. Two seconds isn't much.
You need a proper way of reading the response, or of dealing with the parts as they arrive.
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.
I have created a small server client program for Android. It is working like charm except one thing. First session of file transfer works without any problem, but when I try to send another file, I can't do it without restarting my socket connection. I wanted to achieve this:
1. Start Android server
2. Connect remote client
3. Transfer as many files as one wishes in the same session (without having to restart server and reconnecting client)
How can it be done? Any help would be appreciated!
Here's my code snippet:
Server side methods:
public void initializeServer() {
try {
serverSocket = new ServerSocket(4444);
runOnUiThread( new Runnable() {
#Override
public void run() {
registerLog("Server started successfully at: "+ getLocalIpAddress());
registerLog("Listening on port: 4444");
registerLog("Waiting for client request . . .");
}
});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("Listen failed", "Couldn't listen to port 4444");
}
try {
socket = serverSocket.accept();
runOnUiThread( new Runnable() {
#Override
public void run() {
registerLog("Client connected: "+socket.getInetAddress());
}
});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("Acceptance failed", "Couldn't accept client socket connection");
}
}
Sending file to client:
public void sendFileDOS() throws FileNotFoundException {
runOnUiThread( new Runnable() {
#Override
public void run() {
registerLog("Sending. . . Please wait. . .");
}
});
final long startTime = System.currentTimeMillis();
final File myFile= new File(filePath); //sdcard/DCIM.JPG
byte[] mybytearray = new byte[(int) myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
try {
dis.readFully(mybytearray, 0, mybytearray.length);
OutputStream os = socket.getOutputStream();
//Sending file name and file size to the server
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(myFile.getName());
dos.writeLong(mybytearray.length);
dos.write(mybytearray, 0, mybytearray.length);
dos.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
runOnUiThread( new Runnable() {
#Override
public void run() {
long estimatedTime = (System.currentTimeMillis() - startTime)/1000;
registerLog("File successfully sent");
registerLog("File size: "+myFile.length()/1000+" KBytes");
registerLog("Elapsed time: "+estimatedTime+" sec. (approx)");
registerLog("Server stopped. Please restart for another session.");
}
});
}
Client side (running on PC):
public class myFileClient {
final static String servAdd="10.142.198.127";
static String filename=null;
static Socket socket = null;
static Boolean flag=true;
/**
* #param args
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
initializeClient();
receiveDOS();
}
public static void initializeClient () throws IOException {
InetAddress serverIP=InetAddress.getByName(servAdd);
socket=new Socket(serverIP, 4444);
}
public static void receiveDOS() {
int bytesRead;
InputStream in;
int bufferSize=0;
try {
bufferSize=socket.getReceiveBufferSize();
in=socket.getInputStream();
DataInputStream clientData = new DataInputStream(in);
String fileName = clientData.readUTF();
System.out.println(fileName);
OutputStream output = new FileOutputStream("//home//evinish//Documents//Android//Received files//"+ fileName);
long size = clientData.readLong();
byte[] buffer = new byte[bufferSize];
while (size > 0
&& (bytesRead = clientData.read(buffer, 0,
(int) Math.min(buffer.length, size))) != -1) {
output.write(buffer, 0, bytesRead);
size -= bytesRead;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Try flushing just after
output.write(buffer, 0, bytesRead);
If this still doesn't work I found mine server/client works best with objectoutputstreams that you use in the the following way.
oos = new ObjectOutputStream(socket.getOutputStream());
ois = new ObjectInputStream(socket.getInputStream());
// always call flush and reset after sending anything
oos.writeObject(server.getPartyMembersNames());
oos.flush();
oos.reset();
YourObject blah = (YourObject) ois.readObject();