I wrote a SocketClient for connect to the socket, and add some callback in it.
public class SocketClientV2 {
public static void main(String[] args) {
SocketClientV2.Listener listener = new SocketClientV2.Listener() {
#Override
public void recv(byte[] result) {
// TODO Auto-generated method stub
System.out.println("====recv something");
}
#Override
public void connected() {
// TODO Auto-generated method stub
System.out.println("=====connected!");
}
#Override
public void disconnect() {
// TODO Auto-generated method stub
System.out.println("=====disconnect!");
}
};
SocketClientV2 client = new SocketClientV2("172.16.16.102", 4444,
10000, listener);
byte[] test = new byte[10];
test[0] = (byte) 0x1c;
test[1] = (byte) 0xff;
test[2] = (byte) 0x08;
client.send(test);
}
public interface Listener {
public void recv(byte[] result);
public void connected();
public void disconnect();
}
Socket client = null;
boolean isConnect = false;
OutputStream outputStream = null;
InputStream inputStream = null;
public SocketClientV2() {
}
Listener cb = null;
public SocketClientV2(String site, int port, int timeout, Listener cb) {
this.cb = cb;
try {
client = new Socket(site, port);
client.setSoTimeout(timeout);
System.out.println("Client is created! site:" + site + " port:"
+ port);
if (isConnected()) {
isConnect = true;
if (cb != null) {
cb.connected();
}
checkConnect();
listenRecv();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public Socket getClient() {
return this.client;
}
public void closeSocket() {
try {
isConnect = false;
inputStream.close();
outputStream.close();
client.close();
client = null;
} catch (IOException e) {
e.printStackTrace();
}
}
private boolean isConnected() {
try {
client.sendUrgentData(0xff);
isConnect = true;
} catch (Exception e) {
System.out.println("return false....2");
isConnect = false;
e.printStackTrace();
return false;
}
return true;
}
private void checkConnect() {
new Thread() {
#Override
public void run() {
// TODO Auto-generated method stub
System.out.println("check connect....1");
try {
while (isConnected()) {
Thread.sleep(500);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
System.out.println("finally....3");
if (cb != null) {
cb.disconnect();
}
closeSocket();
}
}
}.start();
}
private void listenRecv() {
new Thread() {
#Override
public void run() {
// TODO Auto-generated method stub
System.out.println("listening Recv....");
try {
inputStream = client.getInputStream();
while (isConnect) {
byte[] result = readStream(inputStream);
if (cb != null) {
cb.recv(result);
}
Thread.sleep(500);
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
}
public void send(final byte[] byteSend) {
new Thread() {
#Override
public void run() {
// TODO Auto-generated method stub
// System.out.println("sendMsg coming....");
if (isConnect) {
try {
outputStream = client.getOutputStream();
outputStream.write(byteSend);
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
}
public byte[] readStream(InputStream inStream) throws Exception {
int count = 0;
while (count == 0) {
// System.out.println(0);
count = inStream.available();
// if(count!=0)
// System.out.println(count);
}
byte[] b = new byte[count];
inStream.read(b);
return b;
}
}
there is one thread checkConnect to check the connect status for the socket..
but it will disconnect after running few mins,
Client is created! site:172.16.16.102 port:4444
=====connected!
check connect....1
listening Recv....
====recv something
====recv something
====recv something
====recv something
====recv something
====recv something
====recv something
return false....2
java.io.IOException: Broken pipe
at java.net.PlainSocketImpl.socketSendUrgentData(Native Method)
at java.net.PlainSocketImpl.sendUrgentData(PlainSocketImpl.java:622)
at java.net.Socket.sendUrgentData(Socket.java:954)
at com.udpdemo.multicast.SocketClientV2.isConnected(SocketClientV2.java:100)
at com.udpdemo.multicast.SocketClientV2.access$0(SocketClientV2.java:98)
finally....3
=====disconnect!
at com.udpdemo.multicast.SocketClientV2$2.run(SocketClientV2.java:121)
java.io.IOException: Stream closed.
at java.net.PlainSocketImpl.available(PlainSocketImpl.java:483)
at java.net.SocketInputStream.available(SocketInputStream.java:217)
at com.udpdemo.multicast.SocketClientV2.readStream(SocketClientV2.java:205)
at com.udpdemo.multicast.SocketClientV2$3.run(SocketClientV2.java:154)
so what's problem with my sendUrgentData???
'Broken pipe' always means that you wrote to a connection which had already been closed by the peer. It's an application protocol error.
But unless the peer of this client isn't written in Java there is no point in using urgent data in the first place. Java can only receive urgent data 'in-line', i.e. after all the other pending data that had already been sent. And that only happens if the peer calls setOOBLine(true), otherwise
by default, this option is disabled and TCP urgent data received on a socket is silently discarded.
It's possible you're doing this to detect a broken connection. In this case, your dream came true, it worked, and all you have to do is adjust your catch and your code accordingly. But this is not in general a reliable technique.
Other notes:
isConnected() can never be false at the point you test it after creating the Socket, and it never magically becomes false afterwards. You need to revisit all the code that calls this method. Most of it doesn't make sense, or relies on false assumptions.
Your readStream() method spin-loops while available() returns zero. There is absolutely no point in this. You're just smoking the CPU. It's also completely at odds with your attempted use of a read timeout, which simply cannot possibly work while this loop is there. The following read() call will block until at least one byte of data arrives, or end of stream or an exception occurs. Your present code will never detect end of stream. You need to completely redesign this part of the code as well. It's poor practice to return a byte array for example.
That same piece of code completely ignores the count returned by read(). Never do that.
Related
I tried to connect with asynchronous socket and read new messages once per second.
I used sample client code (http://www.java2s.com/Tutorials/Java/Java_Network/0080__Java_Network_Asynchronous_Socket_Channels.htm) and in getTextFromUser method I added sleep method (with 1000 ms) and removed read command from user.
Additionally I added additional logic in ReadWriteHandler method. It started work great, but after about one hour program was suspended and has worked (execute my additional logic) not once per second but one per about 10 minutes.
Do you have any idea what might happen?
Part of code:
public void ConnectAsynchr() {
try {
this.channel = AsynchronousSocketChannel.open();
SocketAddress serverAddr = new InetSocketAddress("localhost", PortNumberAsynchr);
Future<Void> result = channel.connect(serverAddr);
try {
result.get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.writeLog("ConnAsynch", "Asynchronous connection succesful established", true);
this.connectAsynch = true;
this.attach = new Attachment();
this.attach.channel = this.channel;
this.attach.buffer = ByteBuffer.allocate(16384);
this.attach.isRead = false;
this.attach.mainThread = Thread.currentThread();
ReadWriteHandler readWriteHandler = new ReadWriteHandler();
this.channel.write(this.attach.buffer, this.attach, readWriteHandler);
try {
this.attach.mainThread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
this.writeLog("ERROR", e.toString(), false);
e.printStackTrace();
}
}
catch (IOException e) {
this.writeLog("ERROR", e.toString(), false);
System.out.println(e);
}
}
class Attachment {
AsynchronousSocketChannel channel;
ByteBuffer buffer;
Thread mainThread;
boolean isRead;
}
class ReadWriteHandler implements CompletionHandler<Integer, Attachment> {
#Override
public void completed(Integer result, Attachment attach) {
if (attach.isRead) {
attach.buffer.flip();
Charset cs = Charset.forName("UTF-8");
int limits = attach.buffer.limit();
byte bytes[] = new byte[limits];
attach.buffer.get(bytes, 0, limits);
String msg = new String(bytes, cs);
writeLog("Asynchr Msg rec", msg, false);
AsynchrMessLogic(msg);
try {
msg = this.getTextFromUser();
} catch (Exception e) {
e.printStackTrace();
}
if (msg.equalsIgnoreCase("bye")) {
attach.mainThread.interrupt();
return;
}
attach.buffer.clear();
byte[] data = msg.getBytes(cs);
attach.buffer.put(data);
attach.buffer.flip();
attach.isRead = false; // It is a write
attach.channel.write(attach.buffer, attach, this);
}else {
attach.isRead = true;
attach.buffer.clear();
attach.channel.read(attach.buffer, attach, this);
}
}
#Override
public void failed(Throwable e, Attachment attach) {
e.printStackTrace();
}
private String getTextFromUser() throws Exception{
/*System.out.print("\nPlease enter a message (Bye to quit):");
BufferedReader consoleReader = new BufferedReader(
new InputStreamReader(System.in));
String msg = consoleReader.readLine();
*/
Thread.sleep(threadSleep);
String msg="aaa";
return msg;
}
}
I have class that extends asynchronous task and another class which extends thread.
Client.java
public class Client extends AsyncTask<String, Void, Void>
{
Socket socket;
private SocketClient socketClient;
DataOutputStream out;
#Override
protected Void doInBackground(String... params)
{
// TODO Auto-generated method stub
Log.d("home","Client");
connect();
return null;
}
protected void connect()
{
// TODO Auto-generated method stub
Log.d("home","Connect");
if(socket!=null)
{
disconnect();
return;
}
try
{
String host = "111.111.1.111";
InetAddress in=InetAddress.getByName(host);
socket = new Socket(in,21);
socketClient=SocketClient.handle(this,socket);
Log.d("home","Connection established");
}
catch(Exception e)
{
e.printStackTrace();
Log.d("home","Not Connection established");
}
}
void disconnect()
{
// TODO Auto-generated method stub
try
{
socketClient.setDesonnected(true);
socket.close();
}
catch (Exception e)
{
System.err.println("Error closing client : "+e);
}
socket=null;
}
protected void sendmessage(byte[] commandchannel1)
{
// TODO Auto-generated method stub
byte[] commandchannel=commandchannel1;
try
{
if(out==null)
{
out=new DataOutputStream(socket.getOutputStream());
}
// out.writeInt(commandchannel.length);
out.write(commandchannel);
out.flush();
}
catch(Exception e)
{
e.printStackTrace();
disconnect();
}
}
public void setreceived(String got)
{
// TODO Auto-generated method stub
System.out.println(got);
}
}
SocketClient.java
public class SocketClient extends Thread
{
private boolean desonnected=false;
private static SocketClient socketClient=null;
private Socket socket=null;
private static Client parent;
private DataInputStream in;
customadapter customadapter;
public synchronized void setDesonnected(boolean cr)
{
desonnected=cr;
}
private SocketClient(Client parent, Socket s)
{
super("Client");
this.parent = parent;
socket=s;
setDesonnected(false);
start();
System.out.println(this.parent);
}
public static SocketClient handle(Client client, Socket socket)
{
// TODO Auto-generated method stub
if(socketClient==null)
socketClient=new SocketClient(parent, socket);
else {
if(socketClient.socket!=null) {
try {
socketClient.socket.close();
} catch (Exception e) {
}
}
socketClient.socket=null;
socketClient=new SocketClient(parent,socket);
}
return socketClient;
}
public void run() {
InputStream is = null;
try {
is = socket.getInputStream();
System.out.println(is);
in = new DataInputStream(is);
} catch(IOException e) {
try {
socket.close();
} catch(IOException e2) {
System.err.println("Socket not closed :"+e2);
}
System.out.println("Could not open socket : "+e.getMessage());
parent.disconnect();
return;
}
while(!desonnected) {
try {
String got = readInputStream(in); //in.readLine();
if(got==null) {
//parent.error("Connection closed by client");
parent.disconnect();
break;
}
**parent.setreceived(got);**
} catch(IOException e)
{
if(!desonnected)
{
System.out.println(e.getMessage());
parent.disconnect();
}
break;
}
}//end of while
try {
is.close();
in.close();
//socket.close();
} catch (Exception err) {}
socket=null;
}//end of run
private static String readInputStream(DataInputStream _in) throws IOException
{
StringBuilder sb=new StringBuilder();
String data = "";
int s = _in.read();
if(s==-1)
return null;
data += ""+String.format("%X", s)+ " ";
int len = _in.available();
System.out.println("Len got : "+len);
if(len > 0)
{
byte[] byteData = new byte[len];
_in.read(byteData);
for(byte b:byteData)
{
System.out.println(byteData);
sb.append(String.format("%02X",b));
sb.append(" ");
}
}
data += sb.toString();
System.out.println(data);
return data;
}
}
I am getting exception as Attempt to invoke virtual method on null pointer exception when setreceived(got) is called. How will i overcome this exception.
I am calling the asynchronous task from another Activity as
client=new Client();
client.execute();
I want to return the received value to an activity finally. How can i do this.
Please help.Thanks in Advance
You will have to change handle method. As for initializing SocketClient you have passed parameter parent, which is not initialized yet. So pass 'client' instead of it.
public static SocketClient handle(Client client, Socket socket)
{
// Verify that the socket is open
if(socketClient==null)
socketClient=new SocketClient(client, socket);
else {
if(socketClient.socket!=null) {
try {
socketClient.socket.close();
} catch (Exception e) {
}
}
socketClient.socket=null;
socketClient=new SocketClient(client,socket);
}
return socketClient;
}
im tryin to send an image over socket , the sender part -(android)- looks short and ok, but the receiver part - which is written by java - is supposed to rename the image and save it in the C:/... . but i get nothing there and i cant find any problem with it ..
here is my server code:
public void start() throws InterruptedException {
keepGoing = true;
try
{
// the socket used by the server
ServerSocket serverSocket = new ServerSocket(port);
// infinite loop to wait for connections
while(keepGoing)
{
// format message saying we are waiting
display("Server waiting for Clients on port " + port + ".");
Socket socket = serverSocket.accept(); // accept connection
// if I was asked to stop
if(!keepGoing)
break;
ClientThread t = new ClientThread(socket); // make a hread of it
jobdone=false;
al.add(t); // save it in the ArrayList
t.start();
}
// I was asked to stop
try {
serverSocket.close();
for(int i = 0; i < al.size(); ++i) {
ClientThread tc = al.get(i);
try {
tc.sInput.close();
tc.sOutput.close();
tc.socket.close();
}
catch(IOException ioE) {
// not much I can do
}
}
}
catch(Exception e) {
display("Exception closing the server and clients: " + e);
}
}
// something went bad
catch (IOException e) {
String msg = sdf.format(new Date()) +
" Exception on new ServerSocket: " + e +
"\n";
display(msg);
}
}
/*
* For the GUI to stop the server
*/
protected void stop() {
keepGoing = false;
// connect to myself as Client to exit statement
// Socket socket = serverSocket.accept();
try {
new Socket("192.168.1.2", 1500);
}
catch(Exception e) {
// nothing I can really do
}
}
/*
* Display an event (not a message) to the console or the GUI
*/
private void display(String msg) {
String time = sdf.format(new Date()) + " " + msg;
if(sg == null)
System.out.println(time);
else
sg.appendEvent(time + "\n");
}
// create a server object and start it
public static void shutdown() {
jobdone = true;
}
/** One instance of this thread will run for each client */
class ClientThread extends Thread {
// the socket where to listen/talk
String Type;
Socket socket;
InputStream sInput;
ObjectOutputStream sOutput;
// my unique id (easier for deconnection)
int id;
// Constructore
ClientThread(Socket socket) throws InterruptedException {
// a unique id
id = ++uniqueId;
this.socket = socket;
/* Creating both Data Stream */
System.out.println("Thread trying to create Object I/O Streams");
// create output first
int bytesRead = 0;
int current = 0;
int filesize=65383;
byte [] mybytearray2 = new byte [filesize];
InputStream is = null;
try {
is = socket.getInputStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream("C:/IMG-20130112-WA0011.jpeg");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // destination path and name of file
//FileOutputStream fos = new FileOutputStream("C:/");
BufferedOutputStream bos = new BufferedOutputStream(fos);
try {
bytesRead = is.read(mybytearray2,0,mybytearray2.length);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
current = bytesRead;
do {
try {
bytesRead =
is.read(mybytearray2, current, (mybytearray2.length-current));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(bytesRead >= 0) current += bytesRead;
} while(bytesRead > -1);
try {
bos.write(mybytearray2, 0 , current);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
bos.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long end = System.currentTimeMillis();
//System.out.println(end-start);
try {
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
am i doing any thing wrong guys ? thanks for reading in advance
The file path should be C:// instead of C:/
In a exercise, I have to create an iterator for an InputStream.
The goal is that the user can do :
for(byte b : new InputStreamToIterable(myInputStream)){
//do stuff with byte
}
I finished to create it and it works well, but the Iterator method is not very elegant (lot of try/catch).
#Override
public Iterator<Byte> iterator() {
// TODO Auto-generated method stub
try {
return new Iterator<Byte>() {
int data = is.read();
#Override
public boolean hasNext() {
// TODO Auto-generated method stub
return data != -1;
}
#Override
public Byte next() {
// TODO Auto-generated method stub
if(!hasNext()){
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int a = data;
try {
data = is.read();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return (byte)a;
}
#Override
public void remove() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
};
} catch (IOException e) {
// TODO Auto-generated catch block
throw new UnsupportedOperationException();
}
}
Is there a way to make it nicer ?
You could ...
in method next(): unify the two try-catch blocks into a single one
do the assignment int data = is.read(); in a constructor, using a try-catch-block, and so get rid of the outermost try-catch-block.
When catching the IOExceptions, instead of simply calling e.printStackTrace(); and continuing program execution, a better practice would be to enable users of this class to programmatically treat the error by re-throwing some RuntimeException (which needn't be declared and so doesn't violate the Iterable interface):
catch(IOException e) {
throw new RuntimeException(e);
}
You could clean it up somewhat by combining the two try-catch blocks in next():
boolean isClosed = false;
#Override
public Byte next() {
if(isClosed) throw new NoSuchElementException();
int a = data;
try {
if(!hasNext()) {
is.close();
isClosed = true;
} else
data = is.read();
} catch(IOException e) { throw new RuntimeException(e); }
return (byte)a;
}
EDIT
Changed the code according to discussion below
I'm trying to implement multiplayer in a game I've been writing, and I've gotten everything to successfully connect (I think..), but when I'm running it, there's an EOFException thrown by the client, and the object (an ArrayList) isn't successfully received.
Code for the server thread:
class ServerThread implements Runnable
{
ServerSocket server = null;
Socket controlSocket = null;
ObjectOutputStream outStream = null;
ObjectInputStream inStream = null;
#Override
public void run() {
setupConnection();
while(true){
sendObject(out.getStuff());
}
}
void setupConnection(){
Log.e("OUTPUTSHOOTER","init-connect");
try {
server = new ServerSocket(SERVERPORT);
Log.e("OUTPUTSHOOTER","server initiated port: "+SERVERPORT);
controlSocket = server.accept();
Log.e("OUTPUTSHOOTER","connected");
inStream = new ObjectInputStream(controlSocket.getInputStream());
outStream = new ObjectOutputStream(controlSocket.getOutputStream());
} catch (StreamCorruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.e("OUTPUTSHOOTER",server+" "+controlSocket+" "+inStream+" "+outStream);
}
public Object recieveObject(){
Object o = null;
try {
o = inStream.readObject();
} catch (OptionalDataException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return o;
}
public void sendObject(Object o)
{
try {
outStream.writeObject(o);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
And then the code for the client:
class ClientThread implements Runnable
{
Socket controlSocket = null;
ObjectOutputStream outStream = null;
ObjectInputStream inStream = null;
#Override
public void run() {
setupConnection();
while(true){
Log.e("OUTPUTSHOOTER","recieving");
Object in = recieveObject();
if(in!= null && in instanceof ArrayList)
{
Log.e("OUTPUTSHOOTER","loading");
out.load((ArrayList<UniverseObject>)in);
}
}
}
void setupConnection(){
Log.e("OUTPUTSHOOTER","ip: "+SERVERIP);
while(controlSocket == null) {
try {
controlSocket = new Socket(SERVERIP,SERVERPORT);
Log.e("OUTPUTSHOOTER","socket connected");
} catch (IOException e) {
e.printStackTrace();
}
}
try {
Log.e("OUTPUTSHOOTER","attempting streams");
outStream = new ObjectOutputStream(controlSocket.getOutputStream());
Log.e("OUTPUTSHOOTER","output working");
inStream = new ObjectInputStream(controlSocket.getInputStream());
Log.e("OUTPUTSHOOTER","streams connected");
} catch (StreamCorruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Object recieveObject(){
Object o = null;
try {
o = inStream.readObject();
} catch (OptionalDataException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return o;
}
public void sendObject(Object o)
{
try {
outStream.writeObject(o);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
What does this mean? And perhaps more importantly, how can I fix it? Thanks in advance..
I don't see you closing your outputstream.
See this SO topic: Problem serializing and deserializing ArrayList
Turns out the server wasn't properly initiating it's input and output streams, even though its sockets were successful. Dunno why, but it only works if I started with the output stream first, then the input (?). Having some other really strange bugs, but at least the communication seems to work.. I'll look more in to them before posting here about it. Thanks guys!