Protobuf how to receive string and object multiple times - java

I am using a server and a client. The client only should deserialize the received protobuf message if the string "yes" is received.
EDIT:
The first message of protobuf is received well. But, if I want to send multiple messages at a time, it gives me:
System.OverflowException: Number overflow.
at ProtoBuf.ProtoReader.TryReadUInt32Variant (System.IO.Stream source, System.UInt32& value)
I read through this link, but I can't figured out what I should do in my case...
I am using TCP sockets. Here is an example code:
Client C#:
TcpClient tcpClient = new TcpClient(host, port);
NetworkStream netStream = tcpClient.GetStream();
StreamReader reader = new StreamReader(netStream);
while(true)
{
// Read multiple messages one after another.
string message = reader.ReadLine();
if(message.Equals("yes"))
{
Command command = Serializer.DeserializeWithLengthPrefix<Command> (netStream, PrexiStyle.Base128);
BinaryWriter bw = new BinaryWriter(File.Open(path, FileMode.Create));
bw.Write(command.File);
bw.Flush();
bw.Close();
}
}
Server Java:
OutputStream outputStream = clientSocket.getOutputStream();
PrintWriter writer = new PrintWriter(outputStream, true);
try{
// send "yes" and the protobuf messages ten times one after another
for(int i=0; i<10; i++)
{
writer.println("yes");
command.writeDelimitedTo(outputStream);
}
}catch(Exception e)
e.printStackTrace();
}
finally{
outputStream.close();
clientSocket.close();
}
My .proto file and proto contract has the same types. It works if I don't want to send a string, but only the protobuf message.
How can I solve this with using a string before deserializing the protobuf message? Is it possible?

Try separating protobuf data and other data in different sockets. Added a while loop to be able to read multiple messages from server.
using System.Threading;
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
// Protobuf data is read on this socket
TcpClient tcpClient = new TcpClient(host, port);
NetworkStream netStream = tcpClient.GetStream();
StreamReader reader = new StreamReader(netStream);
BinaryWriter bw = new BinaryWriter(File.Open(path, FileMode.Create));
bool running = true;
while(running)
{
bw.Write(Serializer.DeserializeWithLengthPrefix<Command>(netStream, PrexiStyle.Base128).File);
}
bw.Flush();
bw.Close();
}).Start();
// Other data is read no this socket
TcpClient tcpClientForOtherStuff = new TcpClient(host, port);
NetworkStream netStream = tcpClientForOtherStuff.GetStream();
StreamReader readerForOtherStuff = new StreamReader(netStream);
string message;
bool running = true;
BinaryWriter bwForOtherStuff = new BinaryWriter(File.Open(path2, FileMode.Create));
bool running = true;
while(running) bwForOtherStuff.Write(readerForOtherStuff.ReadLine());
bwForOtherStuff.Flush();
bwForOtherStuff.Close();
I have not tested or compiled the code.

Related

TCPClient - Send & Receive Response

I'm connecting to a remote TCP Listener that receives a string, and responds with a response.
Going from my Windows 8 Phone App, to a Java Jar. The Jar IS receiving the message, but the Windows 8 Phone App is not getting the response.
C# Code
outputClient.Connect (/IP ADDRESS/, /Port/);
using (Socket sock = outputClient.Client) {
sock.Send (UTF8Encoding.ASCII.GetBytes (broadcastMessage));
var response = new byte[100];
sock.Receive (response);
var str = Encoding.ASCII.GetString (response).Replace ("\0", "");
Console.WriteLine ("[RECV] {0}", str);
} <-- JAVA CODE DOESN'T GET HIT UNTIL THIS LINE IS COMPLETED
Java Code
String clientSentence;
ServerSocket socketServer = new ServerSocket(/* PORT */);
while (true)
{
Socket connectionSocket = socketServer.accept();
connectionSocket.setKeepAlive(true);
BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
clientSentence = inFromClient.readLine();
BufferedWriter outToClient = new BufferedWriter(new OutputStreamWriter(connectionSocket.getOutputStream()));
if (clientSentence != null)
{
try
{
JsonObject json = new JsonParser().parse(clientSentence).getAsJsonObject();
String un = json.get("Username").toString();
String uuid = "2c9c79a096ef4d869fb1d1e07469bb41".replaceAll(
"(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})",
"$1-$2-$3-$4-$5");
var val = /* Get val */
String response = gson.toJson(val);
outToClient.write(response);
outToClient.newLine();
outToClient.flush();
}
catch (Exception ex)
{
ex.printStackTrace();
outToClient.write(response);
outToClient.newLine();
outToClient.flush();
}
}
connectionSocket.close();
}
A little more explanation: JAVA CODE DOESN'T GET HIT UNTIL THIS LINE IS COMPLETED means that the socket appears to not be sending until using (Socket sock = outputClient.Client) is no longer being used.
I fixed it by replacing the C# code with:
using (TcpClient client = new TcpClient (/IP ADDRESS/, /PORT/))
using (NetworkStream stream = client.GetStream ())
using (StreamReader reader = new StreamReader (stream))
using (StreamWriter writer = new StreamWriter (stream)) {
writer.AutoFlush = true;
foreach (string lineToSend in linesToSend) {
Console.WriteLine ("Sending to server: {0}", lineToSend);
writer.WriteLine (lineToSend);
string lineWeRead = reader.ReadLine ();
Console.WriteLine ("Received from server: {0}", lineWeRead);
Thread.Sleep (2000); // just for effect
}
Console.WriteLine ("Client is disconnecting from server");
}

XML Response time ejabberd

At the moment I'm trying to develop an Android Application for Instant Messaging. I want to use ejabberd for this on an Ubuntu Server. There is just one problem.
When I try to connect to my ejabberd first with this xml-line:
<stream:stream to='x.x.x.x' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>
it takes very long to receive the answer (about 20 seconds, sometimes longer).
I just have this problem, when I send some "good" data to the Server. Sending some "bad" data, i receive the Error message very fast.
It's performed by an Android IntentService
I will Post my Code here too:
the attributes:
private Socket socket;
private String host = "x.x.x.x";
private int port = 5222;
private OutputStream out = null;
private String in = null;
the doInBackground():
this.socket = new Socket(host,port);
if(!this.socket.isConnected()){
Log.e("Socket","Socket nicht geöffnet");
}else{
Log.e("Socket","Socket erfolgreich geöffnet");
//create output stream
try {
this.out = socket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
//write to output stream
StringBuffer stringbuffer = new StringBuffer();
stringbuffer.append("<stream:stream to='5.175.8.41' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>");
//convert into bits and give it to outputstream
try {
this.out.write(String.valueOf(stringbuffer).getBytes("UTF-8"),0,String.valueOf(stringbuffer).getBytes().length);
out.flush();
Log.e("Connecting-out","Erstes Tupel erfolgreich gesendet.");
} catch (IOException e) {
e.printStackTrace();
}
//receive the answer from server
try {
Log.e("lol","lol");
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"),200);
StringBuilder builder = new StringBuilder();
String aux;
aux = in.readLine();
this.in = builder.toString();
Log.e("...",aux);
} catch (IOException e) {
e.printStackTrace();
}
Log.e("Connecting-in",in);
i think especially these lines
StringBuilder builder = new StringBuilder();
String aux;
aux = in.readLine();
this.in = builder.toString();
take very long. But the strange thing is , that the Error message is read very fast. So it has to be the Server?
Can someone please help me?
Thanks in advance :)
You used readLine() and it waits for new line character.
On error, server generally disconnects the connection.
It is why you get error answer immediately.
I suggest you not using readLine().

Send string to client upon command JAVA

So I am trying to have a sever sit and listen waiting for a connection from a client. The client sends over some string and the sever does some action based on whats received. Now what I would like to happen is the client sends over some command asking for data back and have the server get what it needs to and send the string back.
Not a big deal right? Well for some reason I can't get it working, my best guess is that its not closing the socket properly. I can't figure out why it wouldn't or what I am doing wrong.
Client
String data = "";
DataOutputStream outToServer = null;
BufferedReader input;
try {
outToServer = new DataOutputStream(clientSocket.getOutputStream());
outToServer.writeBytes("GETDATA");
outToServer.flush();
input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
data = input.readLine();
Log.d("ANSWER: ", data);
input.close();
} catch (IOException e) {
Log.d("Error: ", e.toString());
}
Server
ServerSocket listeningSocket = new ServerSocket(9008);
BufferedReader fromClient ;
PrintStream os;
while(true) {
Socket clientSocket = listeningSocket.accept();
ServerConnection clientConnection = new ServerConnection(clientSocket);
os = new PrintStream(clientSocket.getOutputStream());
fromClient= new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
if(fromClient.readLine().equals("GETDATA")){
os.println("DATA");
os.flush();
clientSocket.wait();
clientSocket.close();
}
else{
clientConnection.run();
}
}
Any ideas?
here is your error
outToServer.writeBytes("GETDATA");
the right code is
outToServer.writeBytes("GETDATA\n");
as your using readline you should send a full line with line break

Reading Http Get request from a inputstream and sending it to the host. using sockets

i have this assignment where i am supposed to write a proxy server that uses java sockets to handle get requests from a client. I am now stuck and have been looking all over google to find the answer but without success.
Christoffers solution helped my with my first problem. Now that i have updated the code this is what i am using.
The problem is that it only downloads parts of most webpages before it gets stuck on sending the packets back to the client loop. At the moment I cant explain why it is behaving the way it is.
public class MyProxyServer {
//Set the portnumber to open socket on
public static final int portNumber = 5555;
public static void main(String[] args){
//create and start the proxy
MyProxyServer myProxyServer = new MyProxyServer();
myProxyServer.start();
}
public void start(){
System.out.println("Starting MyProxyServer ...");
try {
//create the socket
ServerSocket serverSocket = new ServerSocket(MyProxyServer.portNumber);
while(true)
{
//wait for a client to connect
Socket clientSocket = serverSocket.accept();
//create a reader to read the instream
BufferedReader inreader = new BufferedReader( new InputStreamReader(clientSocket.getInputStream(), "ISO-8859-1"));
//string builder for preformance when we loop over the inputstream and read lines
StringBuilder builder = new StringBuilder();
String host = "";
for (String buffer; (buffer = inreader.readLine()) != null;) {
if (buffer.isEmpty()) break;
builder.append(buffer.replaceAll("keep-alive", "close"));
if(buffer.contains("Host"))
{
//parse the host
host = buffer.replaceAll("Host: ", "");
}
System.out.println(buffer);
}
String req = builder.toString();
System.out.println("finshed reading \n" + req);
System.out.println("host: " + host);
//new socket to send the information over
Socket s = new Socket(InetAddress.getByName(host), 80);
//printwriter to send text over the output stream
PrintWriter pw = new PrintWriter(s.getOutputStream());
//send the request from the client
pw.println(req+"\r\n");
pw.flush();
//create inputstream to receive the web page from the host
BufferedInputStream in = new BufferedInputStream(s.getInputStream());
//create outputstream to send the web page to the client
BufferedOutputStream outbuffer = new BufferedOutputStream(clientSocket.getOutputStream());
byte[] bytebuffer = new byte[1024];
int bytesread;
//send the response back to the client
while((bytesread = in.read(bytebuffer)) != -1) {
System.out.println(bytesread);
outbuffer.write(bytebuffer,0, bytesread);
outbuffer.flush();
}
System.out.println("done sending");
//close the streams
inreader.close();
s.close();
pw.close();
outbuffer.close();
in.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch(RuntimeException e){
e.printStackTrace();
}
}
}
If anyone could explain to me why i cant get it working correctly and how to solve it I would be very grateful!
Thanks in advance.

Transfer a file between Android devices?

I'm making a code and I want to send a mp4 file to another Android device. I have reached to connect both Androids via Wifi and write from one a simple for cycle from 1-20 and the other Android device reads and displays the number that is sent.
Here it is the interesting part of the "sender":
InetAddress serverAddr = InetAddress.getByName(serverIpAddress);
Log.d("ClientActivity", "C: Connecting...");
Socket socket = new Socket(serverAddr, port);
connected = true;
while (connected) {
try {
Log.d("ClientActivity", "C: Sending command.");
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket
.getOutputStream())), true);
for (int i = 1; i < 20; i++) {
out.println(i);
i=i++;
and the "receiver":
serverSocket = new ServerSocket(SERVERPORT);
// listen for incoming clients
Socket client = serverSocket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()),8*1024);
This works great! But I want to send a file from one device to another instead of an int. How can I make this?????
You need to package the data to the stream through a some kind of data format. One way to do this is to use the common MIME data format which is commonly used to send attachment in email.
I have answered other question related to sending binary via socket using this format in the following SO Question - android add filename to bytestream. You could check the accepted answer for that question.
For your reference, I just copied the code for sending and receiving through socket from that question below.
File f = new File(path);
BufferedOutputStream out = new BufferedOutputStream( socket.getOutputStream() );
String filename=path.substring(path.lastIndexOf("/")+1);
// create a multipart message
MultipartEntity multipartContent = new MultipartEntity();
// send the file inputstream as data
InputStreamBody isb = new InputStreamBody(new FileInputStream(f), "image/jpeg", filename);
// add key value pair. The key "imageFile" is arbitrary
multipartContent.addPart("imageFile", isb);
multipartContent.writeTo(out);
out.flush();
out.close();
And the code to read it back below using MimeBodyPart that is part of JavaMail.
MimeMultipart multiPartMessage = new MimeMultipart(new DataSource() {
#Override
public String getContentType() {
// this could be anything need be, this is just my test case and illustration
return "image/jpeg";
}
#Override
public InputStream getInputStream() throws IOException {
// socket is the socket that you get from Socket.accept()
BufferedInputStream inputStream = new BufferedInputStream(socket.getInputStream());
return inputStream;
}
#Override
public String getName() {
return "socketDataSource";
}
#Override
public OutputStream getOutputStream() throws IOException {
return socket.getOutputStream();
}
});
// get the first body of the multipart message
BodyPart bodyPart = multiPartMessage.getBodyPart(0);
// get the filename back from the message
String filename = bodyPart.getFileName();
// get the inputstream back
InputStream bodyInputStream = bodyPart.getInputStream();
// do what you need to do here....
There's an open source project released by Google you can take a look at it and have a general idea about connecting devices and sharing files between them.
Here is the link: android-fileshare

Categories