java.net.Socket don't throw IOException at Android - java

What I DO :
Write an upload program using java.net.Socket at Android Mobile
What I WANT:
Connect the Server, When IOException happens(such as the bad network state,no network etc.),try to connect the server three times
What The Question:
Close the WIFI or Mobile GPRS and just run it, No IOexception happened and APP just stop at this point long long time.
Just See My Code:
try {
do {
socket = new Socket();
SocketAddress socketAddress = new InetSocketAddress(API.UPLOAD_SERVER, API.UPLOAD_PORT);
socket.setPerformancePreferences(1, 0,0);
socket.setSoTimeout(1000);
socket.connect(socketAddress, 2000);
attempt = 3;
} while (attempt < 3);
mListener.onStart();
} catch (SocketException e) {
Log.e("UploadTask","exception");
return;
} catch (UnknownHostException e) {
return;
} catch (IOException ioe) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
return ;
}
attempt++;
if (attempt == 3) {
return;
}
}
Help Me or ...:
I hope someone can help me,I will wait your answer online, Thanks.

you have nothing output or exception if you close WIFI or GPRS. Does this mean you app will run over or you code will stay in one sentence,for example, the "connect" method?
I have a suggestion. If you want to explore the API of android, that's OK. OR
Maybe you can test Connectivity before your socket connect.
private boolean isOpenNetwork() {
ConnectivityManager connManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
if(connManager.getActiveNetworkInfo() != null) {
return connManager.getActiveNetworkInfo().isAvailable();
}
return false;
}
hope this can help..
PS: I have no idea about the direct solution to your question, for I have no idea about the socket realize detail. Maybe someone else can explain it.

Assuming that the "connect" method succeeds (which can happen), the API is build in a way that you get IOException(s) when actually reading/writing to the streams of the socket.
socket = new Socket();
SocketAddress socketAddress = new InetSocketAddress(API.UPLOAD_SERVER, API.UPLOAD_PORT);
socket.setPerformancePreferences(1, 0,0);
socket.setSoTimeout(1000);
socket.connect(socketAddress, 2000);
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
// Now for example, if you want to read some data
int data;
try( data = is.read() ){
// Usual processing
} catch( IOException ){
// Disconnected... try reconnecting etc.
}

Related

How do I optimize this socket code in java?

I'm developing an application that can control mouse from android phone. The problem is communication is very slow with socket mouse lags while moving. I want to move mouse pointer as the user moves his finger on screen. How can I optimize this code?
On computer side I'm using this code
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.out.println("Could not listen on port: 4444");
}
System.out.println("Server started. Listening to the port 4444");
while (true) {
try {
clientSocket = serverSocket.accept();
inputStreamReader = new InputStreamReader(
clientSocket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader);
message = bufferedReader.readLine();
System.out.println(message);
Robot robot = new Robot();
switch (message) {
case "first":
ix = MouseInfo.getPointerInfo().getLocation().x;
iy = MouseInfo.getPointerInfo().getLocation().y;
break;
case "lclickp":
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
break;
case "lclickr":
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
break;
//several more cases
} catch (IOException | AWTException ex) {
System.out.println("Problem in message reading");
}
and I'm using this on android side.
private class SendMessage extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
client = new Socket(Login.IP, 4444); // connect to the server
printwriter = new PrintWriter(client.getOutputStream(), true);
printwriter.write(messsage); // write the message to output stream
printwriter.flush();
printwriter.close();
client.close(); // closing the connection
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
Don't create a new connection per message: keep the socket open. At the server end, process multiple messages per accepted socket, until readLine() returns null.
Now I just beginning learning and I'm not good in socket programming but I think the server should wait for new connections in a separate thread because the ServerSocket.accept() method blocks until there is a connection and causes my app frozen at that line.
Thread conWaitingThread = new Thread(new Runnable(){
while (true){
//try
socket = serverSocket.accept();
//catch
}
void startWaiting(){
comWaitingThread.start();
}
void endWaiting(){
if(conWaitingThread.isAlive()){
conWaitingThread.interrupt();
}
}
and for reading msg from client,
while(input.readLine()!=null){
try{
message = input.readLine();
//ur switch case
}catch (ioException e){
//do catch
}
}
For client side, create socket and iostreams once and let them open. Not close the iostreams as closing iostreams closes the respective socket too. May open socket and io in onCreate and close in onDestroy. Be aware that input.readLine() on serverSide waits the new line char and printWriter.write() does not automatically add that. So you may not get any incoming data although printWriter.flush() is called and you need to concat "\n" on writing.
On the PC Side of things:
Consider refactoring into a few helper classes, perhaps, one for Connect, one for sending updates, and one for Disconnect. Then, you will only need to connect and disconnect once per session.
It's good practice to set a tick rate on both the server and client to prevent over-using CPU time and other resources. There is no need to update mouse coordinates more frequently than the refresh rate of typical monitor can update (60fps / 16.6ms) for example.

Moving from IO to NIO - Networking, IllegalBlockingModeException

I'm attempting to move my networking over from standard IO to NIO and following the few tutorials that there are to attempt to figure it out, while me, myself, and I decided it'd be a great idea to spend my first week rewriting the core for all of the applications logic handling, I never would have imagined that I wouldn't be able to set up the basic networking.
Currently the networking is at a very basic stage, everything is tossed inside of a while-loop and I can't honestly say I've put any attempt into it to make it look nice, considering I haven't a clue what I'm doing my goal was to figure out how to do it first, then go back and give it a makeover.
Here's the code I use to initialize my server:
// Initializes the TCP Server and all of its components.
private void initTcpServer(int port) {
try {
// Create a new selector
Selector socketSelector = SelectorProvider.provider()
.openSelector();
// Create a new non-blocking server socket channel;
this.serverSocketChannel = ServerSocketChannel.open();
this.serverSocketChannel.configureBlocking(false);
// Bind the server socket to the specified address and port
this.serverSocketChannel.socket().bind(
new InetSocketAddress("127.0.0.1", port));
// Register the server socket channel, indicating an interest in
// accepting new connections
this.serverSocketChannel.register(socketSelector,
SelectionKey.OP_ACCEPT);
// Set the selector for the server instance.
this.selector = socketSelector;
} catch (IOException e) {
e.printStackTrace();
}
}
Then this class implements the Runnable interface, and a new thread is started directly after this method completes, in this thread we contain the following code:
public void run() {
while (isRunning) {
try {
selector.selectNow();
} catch (IOException io) {
return;
}
Iterator<SelectionKey> it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey key = it.next();
if (!key.isValid()) {
it.remove();
continue;
}
try {
if (key.isAcceptable()) {
this.handleConnection(key);
} else if (key.isReadable()) {
Connection connection = (Connection) key.attachment();
if (connection != null) {
try {
connection.getMasterProtocol()
.decode(connection,
connection.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
}
} finally {
it.remove();
}
}
}
}
This, from my understanding is what allows us to handle our connections and data based off of a SelectionKey.. and is what all of the NIO based networking runs from, you'll see that I'm calling two different methods to make this not so much of a mess, the first one is #handleConnection and the other one is a decode function.
The handle connection method creates a new instance of my Connection class and attatches it to the SelectionKey, like so:
public Connection(SelectionKey key) {
try {
// For an accept to be pending the channel must be a server socket channel.
ServerSocketChannel serverSocketChannel = (ServerSocketChannel)key.channel();
// Accept the connection and make it non-blocking.
this.socketChannel = serverSocketChannel.accept();
this.socketChannel.configureBlocking(false);
// Set up other user data.
this.inputStream = new DataInputStream(socketChannel.socket().getInputStream());
this.masterProtocol = new MasterProtocol();
// Register the new SocketChannel with our Selector, indicating
// we'd like to be notified when there's data waiting to be read.
key = this.socketChannel.register(OGServer.getInstance().getSelector(), SelectionKey.OP_READ);
key.attach(this);
// Add the current <SelectorKey, Connection> to the current connections collection.
connections.put(key, this);
Log.debug(getClass(), "Connection constructed successfully.");
} catch(IOException e) {
e.printStackTrace();
}
}
The error is called when I attempt to call the MasterProtocol#decode method, which looks like this:
public Object decode(Connection connection, DataInputStream dataInputStream) throws IOException {
if(connection.getState() == ConnectionState.CONNECTED) {
byte[] bytes = ByteStreams.toByteArray(dataInputStream);
if(bytes.length < 4) {
System.out.println("Not enough bytes read.");
return null;
}
int bufferSize = dataInputStream.readInt();
System.out.println("Buffer Size: " + bufferSize);
while(bytes.length < bufferSize) {
return null;
}
int test = dataInputStream.readInt();
System.out.println("Test: " + test);
return null;
}
return null;
}
The error seems to be called when the DataInputStream tries to read from the network, more specifically on this line of code:
byte[] bytes = ByteStreams.toByteArray(dataInputStream);
The error:
Exception in thread "Thread-0" java.nio.channels.IllegalBlockingModeException
at sun.nio.ch.SocketAdaptor$SocketInputStream.read(SocketAdaptor.java:190)
at sun.nio.ch.ChannelInputStream.read(ChannelInputStream.java:103)
at java.io.DataInputStream.read(DataInputStream.java:100)
at com.google.common.io.ByteStreams.copy(ByteStreams.java:70)
at com.google.common.io.ByteStreams.toByteArray(ByteStreams.java:115)
at net.ogserver.framework.net.protocol.MasterProtocol.decode(MasterProtocol.java:29)
at net.ogserver.framework.net.OGServer.run(OGServer.java:146)
at java.lang.Thread.run(Thread.java:745)
The 'IllegalBlockingModeException' exception is what's throwing me off, as all of the information I've found was for setting up a Non-blocking server, but the DataInputStream implementation was my own, so I must have done something wrong somewhere. NIO is a completely different world from IO, but learning is learning, eh?
EDIT: I guess it'd help to know how I'm sending the data from the client, it's just a very basic test application that does this:
socket = new Socket("127.0.0.1", 5055);
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeBoolean(false);
If you're moving to NIO in non-blocking you can't keep using streams. If you want to use streams there is no advantage to using NIO at all. I would just stop the migration project now.

Socket closed before able to read from ObjectInputStream(BufferedInputStream(Socket.getInputStream))

I have written a small Client/Server Program which already worked once but after adding Threads and some real input Data to it, i always get a closed Socket before being able to read the Object (the String). The Program always Prints "Client has already closed Connection!" from Function handleConnection in the ProcessDataThread.
ClientCode:
synchronized private static void sendToServer(){
Socket clientSocket = null;
BufferedOutputStream socketOut = null;
ObjectOutputStream out = null;
try{
String xmlToSend = "<startTag>\n<someOtherTag id=\"5555\">\n12345\n</someOtherTag>\n</startTag>\n";
Log.d(TAG, "Trying to send the following to the Server:" + xmlToSend);
//TODO load these from file
clientSocket = new Socket( "10.0.2.2", 7777);
socketOut = new BufferedOutputStream(clientSocket.getOutputStream());
out = new ObjectOutputStream(socketOut);
out.writeObject(xmlToSend);
out.flush();
}catch(Exception ex){
Log.e(TAG, "Could not write File to Server.", ex);
}
finally{
try{
if(clientSocket != null){
clientSocket.close();
}
if(out != null){
out.close();
}
}catch(IOException ex){
Log.e(TAG, "Could not close Socket.");
}
}
}
ServerCode:
ReceiverThread:
public void run()
{
try {
ServerSocket server = new ServerSocket(port);
//Only block for 10 Seconds and try again
server.setSoTimeout(10000);
while(!server.isClosed() && !stopped){
//Run
Socket client = null;
try
{
client = server.accept();
System.out.println("Accepted ClientConnection from " + client.getRemoteSocketAddress());
new ProcessDataThread(client).start();
}
catch( SocketTimeoutException tx){
//nothing
}
catch ( IOException e ) {
e.printStackTrace();
}
finally {
if ( client != null )
try { client.close(); } catch ( IOException e ) { e.printStackTrace(); }
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
ProcessDataThread:
public class ProcessDataThread extends Thread {
Socket client;
public ProcessDataThread(Socket sock) {
// xmlToProcess = xmlString;
this.client = sock;
}
private String handleConnection() {
BufferedInputStream socketIn = null;
ObjectInputStream in = null;
String xmlToProcess = null;
try {
if(!client.isClosed()){
System.out.println("Trying to read from Stream;");
socketIn = new BufferedInputStream(client.getInputStream());
in = new ObjectInputStream(socketIn);
Object xmlString = in.readObject();
System.out.println("Read some Object from Stream:" + xmlString.toString());
if (xmlString instanceof String) {
xmlToProcess = (String) xmlString;
System.out.println("Received the following XML:\n" + xmlToProcess);
}
}else{
System.out.println("Client has already closed Connection!");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (EOFException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (socketIn != null) {
socketIn.close();
}
if(client != null){
client.close();
}
} catch (IOException ioex) {
ioex.printStackTrace();
}
}
return xmlToProcess;
}
#Override
public void run() {
String xmlToProcess = handleConnection();
if (xmlToProcess == null || xmlToProcess.isEmpty()) {
// Es konnte kein String vom Client gelesen werden.
return;
}
System.out.println(xmlToProcess);
}
}
I made some changes with jboi's Suggestions. This is what i got now. The error stays the same. I don't even get to reading the Stream in the Server because client.getClosed()
is always true!
In the Client Code:
clientSocket = new Socket( "10.0.2.2", 7777);
clientSocket.setTcpNoDelay(true);
socketOut = new BufferedOutputStream(clientSocket.getOutputStream());
out = new ObjectOutputStream(socketOut);
out.writeObject(xmlToSend);
out.flush();
socketOut.flush();
//Close Output on Socket to signalize the Server that we finished writing!
clientSocket.shutdownOutput();
in = clientSocket.getInputStream();
byte[] receivedData = new byte[8192];
while(in.read(receivedData) != -1) {
//Wait for the Server to Close the Connection
}
In the Server Code
socketIn = new BufferedInputStream(client.getInputStream());
in = new ObjectInputStream(socketIn);
Object xmlString = in.readObject();
System.out.println("Read some Object from Stream:" + xmlString.toString());
if (xmlString instanceof String) {
xmlToProcess = (String) xmlString;
System.out.println("Received the following XML:\n" + xmlToProcess);
}
out = client.getOutputStream();
out.write(1);
//Signalize the Client that we have read everything
client.shutdownOutput();
It is very probable that your client has closed the socket in the finally block before the server was able to read the data.
In your clients finally block you should use socket.shutdownOutput, then read on the client all incoming data till EOF and then close the socket.
On your server you read till EOF and then send an object as kind of acknowledge, e.g. Number of bytes in the message. You also end the send with socket.shutdownOutput() as you've done at the client. This puts again an EOF at the end of the data. This EOF is received by the client and it will finally close the socket.
The issue seems to be the client and server are unable to identify each others state:
Client sending data to server, where server has closed the connection
Server sending/reading data to client , where client has closed the connection
Either are unable to coordinate with each other, solutions could be to establish a proper state machine. Some examples in Google if you search for (client and server state machine) gives mathematically definite state machine examples for your application: hope this comment helps.
Hence it's not useful to look into this problem in solution perspective and probably start using protocols in place like : telnet etc .
Ok now i'm feeling stupid.
I closed the Socket inside the Server Code myself.
After accepting a connection the following is executed inside the finally Block:
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
The reason that there is this finally Block was because i didn't use Threads before so the ReceiverThread also did handle the Connection and therefore close the socket after using it.
I then moved the code to the new Thread and forgot to remove that finally block!
You can't use a buffered input stream and another kind of stream on the same socket. The buffered stream will steal data from the other one. Make up your mind. The ObjectInputStream will do everything you need. Just use that.
EDIT Re your edit, 'socket closed' means that you closed your socket and then continued to use it.

Bluetooth Server Android - Client Java Bluecove. UUID?

I'm writing an application to communicate between my smartphone and a computer using a bluetooth device.
I'm using Bluecove to manage the bluetooth on the computer, and the android API for my android device.
However, when I'm debugging, nothing happens. I think that the problem is that the UUID is wrong. I'm not sure how to get the devices to identify each other, in order to establish a connection.
I have read some other "questions" about those tags, but what I've tried didn't fix my problem:
Simple Bluetooth data receiver Android
Android: obtaining uuid of a bluetooth device
Etc...
Here's what I've written so far:
For tho android (Server) (This is the function that will make the connection)
public void connectSocket(){
blueAdapter.cancelDiscovery(); // Cancel discovery because it'll slow down the connection
final BluetoothServerSocket serverSocket;
BluetoothServerSocket sSocket= null;
try{
sSocket = blueAdapter.listenUsingRfcommWithServiceRecord("BluetoothJANE", MY_UUID);
}catch(IOException e){}
serverSocket = sSocket;
Thread acceptThread = new Thread(new Runnable() {
#Override
public void run() {
BluetoothSocket socket = null;
while(true){
try{
socket = serverSocket.accept();
}catch(IOException e){
break;
}
if(socket != null){
try{
iStream = socket.getInputStream();
oStream = socket.getOutputStream();
} catch(IOException e){}
}
}
}
});
acceptThread.start();
}
For java app on PC (This is the constructor of the class (it's on an independent thread) that will manage the bluetooth connection)
public ModuleBluetooth() {
StreamConnectionNotifier notifier = null;
StreamConnection connection = null;
try {
blueDevice = LocalDevice.getLocalDevice();
blueDevice.setDiscoverable(DiscoveryAgent.GIAC);
String url = "btspp://localhost:" + MY_UUID.toString()
+ ";name=RemoteBluetooth";
notifier = (StreamConnectionNotifier) Connector.open(url);
} catch (BluetoothStateException e) {
System.out
.println("ModuleBluetooth: Error getting the bluetooth device");
} catch (IOException e) {
}
System.out.println("waiting for connection...");
try {
connection = notifier.acceptAndOpen();
System.out.println("Conenction created");
} catch (IOException e) {
System.out.println("Can not create the connection");
}
}
Could somebody please help me? Any thoughts would be very much appreciated.
I have also tried to use some functions to acquire the UUID (in android) such as, [fetchUuidsWithSdp][2] (and the related functions) but eclipse doesn't recognize that functions (It seems that they don't exist in "my" API).
http://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#fetchUuidsWithSdp%28%29
Try this example, http://luugiathuy.com/2011/02/android-java-bluetooth/ . I also had problem related to UUID, in this example, Converting UUID to 00001101-0000-1000-8000-00805F9B34FB worked out of the box. See this link: http://www.avetana-gmbh.de/avetana-gmbh/produkte/doc/javax/bluetooth/UUID.html

Testing Socket Program

So I wrote a simple Socket program that send message from Client to Server program and wanted to know what is the proper procedure to go about testing this? Both my Client and Server machines are running on Ubuntu 12.04 and I'm remote connecting to both of them.
For my Client code when I instantiate the client socket (testSocket) do I use its IP Address and Port number or Servers IP Address and Port number?
Here is the Code for Client:
public static void main(String[] args) throws UnknownHostException, IOException
{
Socket testSocket = null;
DataOutputStream os = null;
DataInputStream is = null;
try
{
testSocket = new Socket("192.168.0.104", 5932);
os = new DataOutputStream(testSocket.getOutputStream());
is = new DataInputStream(testSocket.getInputStream());
}
catch (UnknownHostException e)
{
System.err.println("Couldn't find Host");
}
catch (IOException e)
{
System.err.println("Couldn't get I/O connection");
}
if (testSocket != null && os != null && is != null)
{
try
{
os.writeBytes("Hello Server!\n");
os.close();
is.close();
testSocket.close();
}
catch (UnknownHostException e)
{
System.err.println("Host not found");
}
catch (IOException e)
{
System.err.println("I/O Error");
}
}
}
Here is the code for Server:
public static void main(String[] args)
{
String line = new String() ;
try
{
ServerSocket echoServer = new ServerSocket(5932);
Socket clientSocket = echoServer.accept();
DataInputStream is = new DataInputStream(clientSocket.getInputStream());
PrintStream os = new PrintStream(clientSocket.getOutputStream());
while (true)
{
line = is.readLine();
os.println(line);
}
}
catch (IOException e)
{
System.out.println(e.getMessage());
}
}
I'm new to Sockets and not sure what I'm supposed be seeing. I compiled both programs in terminal fine but not sure which one should I be running first or do they need to be started simultaneously?
Thanks
Your server is running in a infinite loop. Avoid that.
You have to restart your computer.
while (true)
{
line = is.readLine();
os.println(line);
}
try
while (!line.equals("Hello Server!"))
{
line = is.readLine();
os.println(line);
}
Run the server first. echoServer.accept(); waits for a connection. When it gets the first connection,
http://docs.oracle.com/javase/tutorial/networking/sockets/ this is a short java tutorial on how to work with sockets and also you can learn how to make a server that would accept multiple connections at a time. This tutorial explains you always need to start the server first, which is only logical. You should use threads to manage connections and then close them so that you use resources efficiently

Categories