I need your help. I want to do this: I have a socket TCP and a Timer task in my IntentService. This is my code:
protected void onHandleIntent(Intent intent)
{
String add = intent.getStringExtra("address");
Log.d("add",add);
int porta = Integer.parseInt(intent.getStringExtra("port"));
InetAddress serverAddr = null;
try
{
serverAddr = InetAddress.getByName(add);
socket = new Socket(serverAddr, porta);
socketHandler.setSocket(socket);
final PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
out.print("go");
out.flush();
final byte[] bytes = new byte[1000];
int counter;
String reader;
final InputStream data = socket.getInputStream();
int numRead = 0;
if ((numRead = data.read(bytes)) >= 0)
{
reader=new String(bytes, 0, numRead);
}
if (reader.equals("Let's go"))
{
//socket connected
}
pingTimer = new Timer();
pingTimer.scheduleAtFixedRate(new TimerTask() {
String reader; int r;
public void run()
{
out.write("ping");
out.flush();
if(out.checkError())
{
onDestroy();
}
}
}, 0, 20000);
InputStream readeIn = socket.getInputStream();
char [] buffer = new char[1024];
BufferedReader in = new BufferedReader(new InputStreamReader(readeIn));
while((counter = in.read(buffer)) != -1)
{
//read here
}
catch (UnknownHostException e)
{
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
onDestroy();
}
}
public void onDestroy()
{
//destroy socket
}
and it works well. Now I want to do this: I want to put a timer to the socket. So, the socket is up for 3 minutes; if it receives something, re-put 3 minutes to listen, but if in these 3 minutes socket doesn't receive anything, I want to close the socket. How can I do it?
Thanks for your answers.
You need to call Socket.setSoTimeout() with an argument of 3*60*1000 which corresponds to three minutes (times 60 to give seconds, times 1000 to give milliseconds), and handle the resulting SocketTimeoutException accordingly.
Related
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
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 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();
Need help... I have understood how to make server-client socket conection... It works fie... Now I want to transfer files from server to client and back.... here are my sources...
Socket server...
public class ServerActivity extends Activity {
private TextView serverStatus;
// default ip
public static String SERVERIP = "192.168.1.1";
// designate a port
public static final int SERVERPORT = 8080;
private Handler handler = new Handler();
private ServerSocket serverSocket;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
serverStatus = (TextView) findViewById(R.id.server_status);
SERVERIP = getLocalIpAddress();
Thread fst = new Thread(new ServerThread());
fst.start();
}
public class ServerThread implements Runnable {
public void run() {
try {
if (SERVERIP != null) {
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Listening on IP: " + SERVERIP);
}
});
serverSocket = new ServerSocket(SERVERPORT);
while (true) {
// listen for incoming clients
Socket client = serverSocket.accept();
/////////////////////////////////
File myFile = new File ("/sdcard/frostwire.apk");
byte [] mybytearray = new byte [(int)myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
OutputStream os = client.getOutputStream();
System.out.println("Sending...");
serverStatus.setText("sending 123.exe...");
os.write(mybytearray,0,mybytearray.length);
os.flush();
client.close();
////////////////////////////
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Connected.");
}
});
try {
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
Log.d("ServerActivity", line);
handler.post(new Runnable() {
#Override
public void run() {
// do whatever you want to the front end
// this is where you can be creative
}
});
}
break;
} catch (Exception e) {
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Oops. Connection interrupted. Please reconnect your phones.");
}
});
e.printStackTrace();
}
}
} else {
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Couldn't detect internet connection.");
}
});
}
} catch (Exception e) {
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Error");
}
});
e.printStackTrace();
}
}
}
// gets the ip address of your phone's network
private String getLocalIpAddress() {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress()) { return inetAddress.getHostAddress().toString(); }
}
}
} catch (SocketException ex) {
Log.e("ServerActivity", ex.toString());
}
return null;
}
#Override
protected void onStop() {
super.onStop();
try {
// make sure you close the socket upon exiting
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Socket Client...
public class ClientActivity extends Activity {
private EditText serverIp;
private Button connectPhones;
private String serverIpAddress = "";
private boolean connected = false;
private Handler handler = new Handler();
int filesize; // filesize temporary hardcoded
long start = System.currentTimeMillis();
int bytesRead;
int current = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.client);
serverIp = (EditText) findViewById(R.id.server_ip);
connectPhones = (Button) findViewById(R.id.connect_phones);
connectPhones.setOnClickListener(connectListener);
}
private OnClickListener connectListener = new OnClickListener() {
#Override
public void onClick(View v) {
if (!connected) {
serverIpAddress = serverIp.getText().toString();
if (!serverIpAddress.equals("")) {
Thread cThread = new Thread(new ClientThread());
cThread.start();
}
}
}
};
public class ClientThread implements Runnable {
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
Log.d("ClientActivity", "C: Connecting...");
Socket socket = new Socket(serverAddr, ServerActivity.SERVERPORT);
connected = true;
////////// // receive file
byte [] mybytearray = new byte [filesize];
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream("/sdcard/frostwire.apk");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead;
do {
bytesRead =
is.read(mybytearray, current, (mybytearray.length-current));
if(bytesRead >= 0) current += bytesRead;
} while(bytesRead > -1);
bos.write(mybytearray, 0 , current);
bos.flush();
long end = System.currentTimeMillis();
System.out.println(end-start);
bos.close();
socket.close();
//////////////////////////////
while (connected) {
try {
Log.d("ClientActivity", "C: Sending command.");
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket
.getOutputStream())), true);
// where you issue the commands
out.println("Hey Server!");
Log.d("ClientActivity", "C: Sent.");
} catch (Exception e) {
Log.e("ClientActivity", "S: Error", e);
}
}
socket.close();
Log.d("ClientActivity", "C: Closed.");
} catch (Exception e) {
Log.e("ClientActivity", "C: Error", e);
connected = false;
}
}
}
}
Pieces of source which are marked by "///////" don't work.... Help
Better you replace the following your code
do {
bytesRead =
is.read(mybytearray, current, (mybytearray.length-current));
if(bytesRead >= 0) current += bytesRead;
} while(bytesRead > -1);
with the following one
do {
bytesRead =is.read(mybytearray, current, (mybytearray.length-current));
if(bytesRead > 0)
{
current += bytesRead;
}
} while(bytesRead > 0);
Then try it
after going through above discussion i would like to add few comments-
Have you added permission code for reading sdcard in android manifest file ? If not you should add following code as the server is accessing External Storage. Do for the client also to write in external storage.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Else, the directory you have provided is not correct. Check the directory.
In the client program, you have defined file_size which is not assigned any value nowhere in the program.
I would also like to suggest that, the file_size in the client program should be greater than the file to be transfer and size is in byte.
I need to use the tcp socket connection to get the data from a bluebox, if I input a comment, such as "getcolor", the bluebox will send me the information like"red, blue".
In this case the bluebox as a server and I do not need to program on it, but I have problem to show the information on the EditText.
public class sender {
public static void main(String[] args)throws IOException{
Socket socket = new Socket("192.168.1.176",14111);
OutputStream out = socket.getOutputStream();
BufferedReader msg = new BufferedReader(new InputStreamReader(System.in));
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter ou = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out)),true);
String buffer = new String("");
String ms = "";
while(true)
{
while(in.ready())
buffer+= in.readLine()+ "\n";
String[] line = buffer.split("\n");
while(msg.ready())
ms = msg.readLine();
if(ms.equals("exit"))
{
break;
}
if(!ms.equals(""))
{
ou.println(ms);
ou.flush();
ms = "";
}
if(!buffer.equals(""))
{
System.out.print(buffer);
buffer = "";
}
}
in.close();
out.close();
socket.close();
}
}
this java code works, but it fails in the android code below:
public class BlueBoxApp extends Activity {
/** Called when the activity is first created. */
Context appInstance = this;
private EditText info;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
info = (EditText)findViewById(R.id.EditText01);
try{
InetAddress serverAddr = InetAddress.getByName("192.168.1.176");//TCP服务器IP地址
Log.d("TCP", "server,receiving...");
Socket socket = new Socket(serverAddr,14111);
try {
OutputStream out = socket.getOutputStream();
BufferedReader msg = new BufferedReader(new InputStreamReader(System.in));
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter ou = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out)),true);
String buffer = new String("");
String ms = "getsensorno";
Log.d("TCP", "sending:'"+ms+"'");
while(true)
{
while(in.ready())
buffer+= in.readLine()+ "\n";
while(msg.ready())
ms = msg.readLine();
if(ms.equals("exit"))
{
break;
}
if(!ms.equals(""))
{
ou.println(ms);
ou.flush();
ms = "";
}
if(!buffer.equals(""))
{
info.setText(buffer);
buffer = "";
}
}
} catch (Exception e) {
Log.e("TCP", "error",e);
}finally{
socket.close();
}
}catch(Exception e){
Log.e("TCP", "error",e);
}
}
}
what is the problem and how to set a thread for it? Thanks!
The problem, as you indicated, is that you are doing the networking part on the main thread.
Setting a new thread is easy, consider using AsyncTask. Please read the documentation (which is very good) before jumping to implement it, it will make it much easier IMHO.
Also, make sure you have internet permission in your AndroidManifest.xml