Situation: : I must either send a parameter to the server, or a serialized object. It can be in any random order.
What I've done: As per this post, I developed a protocol to let the server know what I'm sending just before I actually send it. If its any string, it just goes via PrintWriter.println().
But just before sending a serialized object via ObjectInputStream, I send a PrintWriter.println("O"). So the server knows it must expect a serialized object next.
Problem: I'm getting the StreamCorruptedException, even though I'm using only one instance of ObjectInputStream at the client throughout the socket's life. Should anything be done at the Server end ?
----------------------- EDITED BELOW ---------------------
Client End:
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(thisSocket.getOutputStream())),
true);
if (!sent){
out.println("Dummy");
sent = true;
}
objectOutputStream.flush();
objectOutputStream.reset();
out.println("#SerialO#"); //This param signals the server
//that an object will be sent next.
if(((calcSum) this.obj).getRemotable()){
/*objectOutputStream.flush();
objectOutputStream.reset();*/
Log.i("ENDPOINT", "Sending Serialized data ...");
objectOutputStream.writeObject(this.obj);
objectOutputStream.flush();
objectOutputStream.reset();
// Get the byte array
byte[] byteArray = byteArrayOutputStream.toByteArray();
}
Server End:
while (!Thread.currentThread().isInterrupted()) {
try{
this.input = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
// NOW DECLARED AND USED IN UpdateUIThread
//PrintStream out = new PrintStream(socket.getOutputStream());
if(!sent)
{
flg = this.input.readLine().toString();
Log.i("SERVER","SERVER Received False flg as "+flg);
sent = true;
}
else{
flg = this.input.readLine().toString();
System.out.println("SERVER Received flg as "+flg);
if(flg.contains("#SerialO#")){ //Be prepared to
// receive a serilized obj from client
//Log.d("SERVER","Received an object");
CommunicationThread commThread = new CommunicationThread(this.clientSocket,it);
new Thread(commThread).start();
}
else
{
//Log.d("SERVER","Received a parameter "+flg);
executor = Executors.newFixedThreadPool(5);
executor.execute(new updateUIThread(this.clientSocket,flg));
}
}
} catch (IOException e) {
e.printStackTrace();
Log.e("SERVER", "Creation went bad -- "+e.toString());
break;
}
catch (Exception e)
{
Log.d("CLIENT TAG", "Creation went bad -- "+e.toString());
}
}
}
...
public CommunicationThread(Socket clientSocket, Intent it) {
this.clientSocket = clientSocket;
try {
Log.d("SERVER","Inside Server's Comm Thread");
if (mInput==null){
Log.i("SERVER","Receiving very first serialized obj");
mOutput = new ObjectOutputStream(this.clientSocket.getOutputStream());
System.out.println("Inside Server's Comm Thread 2 ");
// EXCEPTION OCCURS IN THE LINE BELOW.
mInput = new ObjectInputStream(new BufferedInputStream(this.clientSocket.getInputStream()));
}
You can't mix streams and readers/writers on the same socket if any of them is buffered. In this situation I would use the object stream for everything.
Related
I have implemented Android ServerSocket to work with a payment device in semi integrated mode. Payment device is Android based so it will open a server socket and listens for incoming requests on a fixed port. I have also created a dummy clientApp where I send data/request to payment app and it sends the response back to cleint app. This part works.
The problem arises when I send the same request via an app like Paket Sender. In this case the request is received on server side but when I send the response back to client (Packet Sender) it does not receive anything when connection is active.
Below is my code snippet where I read the data and then send the data.
the part where I create a server socket
ServerSocket serverSocket = new ServerSocket(SERVER_PORT);
Socket socket = serverSocket.accept();
CommunicationThread commThread = new CommunicationThread(socket);
new Thread(commThread).start();
Then the communication thread
class CommunicationThread implements Runnable {
private Socket clientSocket;
private BufferedReader input;
public CommunicationThread(Socket clientSocket) {
//here the clientSocket is used to listen to incoming messages from client
this.clientSocket = clientSocket;
//here this tempClientSocket is used to send messages back to client through sendMessage() methos which is defined below.
tempClientSocket = clientSocket;
try {
this.input = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
showMessage("Error Connecting to Client!!");
}
}
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
//we receive the incoming message in this read variable and from here we parse it and send the request to PayWorks SDK.
String read = input.readLine();
Log.e("READ"," Read->"+read);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
* Using below method we send the message back to the client. We are having problems in this part when client is an application
* like Packet Sender.
* Because we do not know how the underlying parsing of these apps works hence we cant debug it.
* What we have made sure is that result 'message' variable is
* correct here and that tempClientSocket is not null.
* But after that we just send the message over the socket and we do not have further control over it.
* This method works if client is implemented in mobile and have similar implemementation of client code as mentioned on
* android developer Socket implementation guide.
*
private void sendMessage(final String message) {
try {
Log.e("MESSAGES","Message is->"+message);
if (null != tempClientSocket) {
new Thread(new Runnable() {
#Override
public void run() {
PrintWriter out = null;
try {
out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(tempClientSocket.getOutputStream())),
true);
} catch (IOException e) {
e.printStackTrace();
}
out.println(message);
}
}).start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
Can someone help me figuring out what I need to change in sendMessage() method above so that even in applications like Packet Sender I can see the data sent back by the server.
PS- I have tried most of the solutions available on SO regarding this and hence posting this as a last resort.
Today I was writing an app (Android) that received strings from a server in Node.js. The socket connection is fine, I can send from Android to Server just fine, but when it comes to receiving from Server, readUTF() is stuck at reading. Here's the Android code to send and receive:
Socket socket = new Socket("10.13.37.129",1337);
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
JSONObject jsonObject = new JSONObject();
jsonObject.put("data", "Tristen");
dataOutputStream.writeUTF(jsonObject.toString());
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
System.out.println("Receiving");
final byte[] buffer = {};
dataInputStream.read(buffer);
string = new String(buffer);
System.out.println("Received");
Runnable runnable1 = new Runnable() {
#Override
public void run() {
System.out.println("This is the string: " + string);
System.out.println("This is the buffer: " + buffer.length);
System.out.println("This is the buffer.ToString(): " + buffer.toString());
textView.setText(string);
}
};
runOnUiThread(runnable1);
And this is the server code to send the string:
// Add a 'data' event handler to this instance of socket
clientSocket.on('data', function(data) {
console.log('DATA: ' + data);
clientSocket.write('Hello\n');
clientSocket.write('World\n');
});
Can anyone see what's wrong with it?
readUTF() is for reading strings written by DataOutputStream.writeUTF().. Nothing else. Use read(), BufferedReader.readLine(), etc.
I am working on a client/server project, the client being Android and the server being C#.
What I am trying to do is the Android app listens on a UDP socket and the C# server sends a message on that port. Android will then receive the message from the reply, and send back a response.
This is the code I have:
public void run()
{
Log.d(TAG, "Heartbeat manager thread starting");
try
{
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
DatagramSocket socket = new DatagramSocket(HEARTBEAT_PORT);
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
while (!cancelThread)
{
socket.receive(packet);
final String xml = new String(packet.getData(), 0, packet.getLength());
Log.v(TAG, xml);
XmlSettings xmlSettings = new XmlSettings();
xmlSettings.setIndent(true);
XmlWriter writer = new XmlWriter(xmlSettings);
writer.writeStartDocument();
writer.writeStartElement("HeartbeatManager");
writer.writeElementString("Command", Defines.ServerCommands.HeartbeatResponse.toString());
writer.writeEndElement();
buffer = writer.returnXmlOutput().getBytes();
DatagramPacket replyPacket = new DatagramPacket(buffer, buffer.length);
socket.send(replyPacket);
}
}
catch (SocketException ex)
{
Log.e(TAG, "Socket Exception Occurred: " + ex.toString());
}
catch (IOException ex)
{
Log.e(TAG, "IOException Occurred: " + ex.toString());
}
At the moment it throws an exception when I do the socket.send stating that the destination address is null.
You must set the destination address in the DatagramPacket before sending it.
The constructor you're using (without the address) is just for receiving, not for sending.
In UDP protocol, destination is set in the packet because there is not a connection (like TCP)
So in your code you are telling the socket, which has no concecpt of destination to send a packet without destination, so it'll throw and exception.
InetSocketAddress address = InetSocketAddress("www.google.com", 8080);
DatagramPacket replyPacket = new DatagramPacket(buffer, buffer.length, address);
socket.send(replyPacket);
I'm using Android 1.6. In my office there is some application which sends some data via HTTP post method.
I want to add a module send the data via socket.I send the data via socket (output stream) correctly.It receives in server side (c# socket application) socket application correctly.
But in HTTP post method some data are passed as parameter. I'm not able to find any methods in socket to send the some data as parameter and some data in streams.
The following are the code which i done for send data via socket through outpustream .
socket=new Socket(this.ipAddress,this.port_number);
//socket.setSocketImplFactory(fac)
Log.i(tagName, "after creating sokcet");
os=socket.getOutputStream();
is=socket.getInputStream();
dos=new DataOutputStream(os);
Log.i(tagName, "after creating ouput streams");
dis=new DataInputStream(is);
Log.i(tagName, "after creating input streams");
//dos.writeUTF(msg[i].trim());
//dos.write(msg[i].trim().getBytes());
//dos.writeUTF(msg[i].trim());
dos.write(msg[i].trim().getBytes()); //data written as bytes
//dos.writeUTF(str)
dos.flush();
Log.i(tagName, "after writing data to os");
StringBuilder sbuilder=new StringBuilder();
///*
int ch;
byte bt=1;
while((bt=(byte) dis.read())!=-1)
{
Log.i(tagName, "ch="+bt);
byte temp[]=new byte[1];
//temp[0]=(byte)ch;
temp[0]=(byte)bt;
String tempStr1=new String(temp);
Log.i(tagName, "tempstr:"+tempStr1);
sbuilder.append(tempStr1);
Log.i(tagName, "Data fro server : "+sbuilder.toString());
tempStr1=null;
}
//*/
//byte tt[]=new byte[dis.readLine()]
//resultStr=dis.readLine();resultStr=resultStr.trim();
resultStr=sbuilder.toString();
Log.i(tagName, "server res :"+resultStr);
if(dos!=null)
{
try
{
dos.close();
}
catch(Exception ex)
{
}
}
if(dis!=null)
{
try
{
dis.close();
}
catch(Exception ex){}
}
if(socket!=null)
{
try
{
socket.close();
}
catch(Exception ex)
{
}
}
The above coding snippet works correctly.
But in HTTP post method the user name and password as parameter and the actual data in streams. Like that I want to send the username and password in parameter and actual in streams.
I find the solution.
We cannot send the data as parameter like http parameter in socket connection.
We can send the data only in streams.
In server side we can write to parse the data from the streams.
Thanks
public void sendToServer(String fileToSend, String ip, int sendPort)
{
int port = sendPort;
String url = ip;
File file = new File(fileToSend);
String fileName = file.getName();
Socket sock;
try {
sock = new Socket(url,port);
//Send the file name
OutputStream socketStream = sock.getOutputStream();
ObjectOutput objectOutput = new ObjectOutputStream(socketStream);
objectOutput.writeObject(fileName);
//Send File
byte [] mybytearray = new byte [(int)file.length()];
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
OutputStream os = sock.getOutputStream();
os.write(mybytearray,0,mybytearray.length);
fileSentOkay();
os.flush();
sock.close();
} catch (UnknownHostException e) {
hostNotFound();
} catch (IOException e) {
hostNotFound();
}
}
When I try to send something to the server when the server isn't listening for the connection, the phone keeps attempting to send the file. As a result of this, my Android program will eventually force close.
How could I set a time out for this to happen? Would I have to use something like setSoTimeout() on the socket that is sending the data?
First: Just in case: Don't do network stuff on the UI Thread. Bad Things will happen (tm)
Second: setSoTimeout() should give you a timeout in case the server accepts the connection, but does not reply (or in case there is no reply from the network at all). In case the connection is rejected the socket should fail significantly faster.
Edit: In case the constructor of the Socket class is already taking that long, try using the connect(SocketAddress, int) method. Use InetSocketAddress as parameter:
Socket s = new Socket();
s.connect(..., 1000);