I am trying to get a good sample program to send Google protocol buffer messages to and from Java server to c# client. I an using RabbitMQ for this purpose, but I found that RabbitMq service is not that reliable, and crashes some time. As a backup I want to use socket option in case RabbitMq is down.
I have code like this in java
ProtoBuffMessage.MessageProtBuff msgItem = clsBuilder.build();
ByteArrayOutputStream oStream = new ByteArrayOutputStream();
msgItem.writeTo(oStream);
...
...
//Send it to RabbitMQ
m_clsChannel.basicPublish(m_clsAppSettings.getRabbitMqExchangeName(), m_clsAppSettings.getRabbitMqExchangeQueue(), null, oStream.toByteArray());
on C# side I have code like this to receive and parse the data
using (var connection = factory.CreateConnection())
using (var channel = connection.CreateModel())
{
channel.ExchangeDeclare(exchange: "direct_logs",
type: "direct");
var queueName = channel.QueueDeclare().QueueName;
channel.QueueBind(queue: queueName,
exchange: "direct_logs",
routingKey: "amr");
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var body = ea.Body;
var message = Encoding.UTF8.GetString(body);
var routingKey = ea.RoutingKey;
Console.WriteLine(" [x] Received {0}':'{1}'",
routingKey, message);
Messaging.MessageProtBuff.Builder builder = new Messaging.MessageProtBuff.Builder();
builder.MergeFrom(body);
Messaging.MessageProtBuff data = builder.Build();
Console.WriteLine(data.Comment);
}
}
This works with RabbitMq if it is working properly. Now I want to know How do I use sockets to send the same, and receive it at C# client and reconstruct the Object. Preferably I would like to use the same ByteArrayOutputStream oStream object in java code. By converting it to byte array I can send it over the scocket and reconstruct the object at other end.
I have adapted this sample in my code:
http://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html
but in this tutorial they are sending strings. I want to send the byte array. How to do this at java end and how to parse the same at C# end?
Related
Here is my java server code:
public class CaspSocket {
private Socket socket = null;
private PrintWriter out = null;
private BufferedReader in = null;
public CaspSocket(InetAddress caspAddress, int caspPort) throws IOException {
socket = new Socket(caspAddress, caspPort);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
I use "out" to send data
out.print(1 + "|");
out.print(2 + "|");
out.print(3 + "|");
It will be received in GameMaker Studio as follows:
var in_buff = ds_map_find_value(async_load, "buffer");
test_string=buffer_read(in_buff, buffer_string);
This way everything will be put into a single string
test_string="1|2|3|"
However I want to receive the data in in a consecutive way
var in_buff = ds_map_find_value(async_load, "buffer");
test_string=buffer_read(in_buff, buffer_string);
test_string2=buffer_read(in_buff, buffer_string);
test_string3=buffer_read(in_buff, buffer_string);
to give
test_string="1|" test_string2="2|" test_string3="3|"
How do I send data from the java server in a consecutive way so that each chunk of data can be read out individually using buffer_read(in_buff, buffer_string); in GameMaker Studio
Edit:
I have read the using buffers section the problem is when I send in GameMaker Studio to the server using this:
buffer_seek(Buffer, buffer_seek_start, 0);
buffer_write(Buffer, buffer_string, string(1) + chr(10)); //chr(10) means new line
buffer_write(Buffer, buffer_string, string(2) + chr(10));
buffer_write(Buffer, buffer_string, string(3) + chr(10));
network_send_raw(Socket, Buffer, buffer_tell(Buffer));
The java server will only send back one string:
var in_buff = ds_map_find_value(async_load, "buffer");
buffer_read(in_buff, buffer_string);
I don't know how this should be send sequentially using the java server, like it can be received in GM:S:
var in_buff = ds_map_find_value(async_load, "buffer");
test_string=buffer_read(in_buff, buffer_string);
test_string2=buffer_read(in_buff, buffer_string);
test_string3=buffer_read(in_buff, buffer_string);
I will only be using buffer_string to make things easier.
The socket communication is based on the concept of streams. Streams are plain sequence of bytes and there is no way how you can control how they are sent. The actual transport is managed by the OS protocol driver and is not accessible from applicatio level. So based on the multiple conditions
out.print(1 + "|");
// some other code
out.print(2 + "|");
// some other code
out.print(3 + "|");
may be delivered in a single packet or several packets. Even flush() method will just push data to OS buffer and guarantee you nothing about the actual delivery.
So to read messages sequentially you should ether
Know their sizes and read into buffers of expected size (you may send some kind of "header" of fixed size data first which will tell the size of the "body" data next, then next "header" and so on)
Read full available content and split it in your client app using data delimeters (it your case this seem to be | character)
I'm trying to send an message from Java client to C++ server using ProtoBuf over socket. My program hangs while i am trying to create InputStream. Thanks in advance if some one could help me on this and here is my part of client code in java:
String host = "xxxxxxxxx";
int port = xxxx;
Builder builder = CarSelection.Car.newBuilder();
builder.setLabel("Audi");
builder.setValue("A6");
Car car = builder.build();
Socket client = new Socket(host, port);
byte[] result = car.toByteArray() ;
car.writeDelimitedTo(client.getOutputStream());
Car recieveData= car.parseDelimitedFrom(client.getInputStream());
It is able to write to output stream but my program hangs when trying to read from input stream.
My objective: send a local variable from the client program to the server program.
I have the client and server connected, and I know how to send string messages from the client to the server.
Example:
private void sendToServer(Socket clientSocket) throws IOException{
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
writer.write("You have connected to the server.");
writer.flush();
writer.close();
}
The above code works perfectly and sends a message.
But what do I do if I want to send data/variables between a client and a server?
For example what if I had a variable float a = 0.5, or a 2d integer array, etc. how would I send that from client to server or vice-versa?
I tried doing the same thing just using writer.write(a) instead, for example, but the inputs for writer.write() are limited, so I feel like I'm approaching it incorrectly.
If there is a better way for me to try to be sending variables aside from using BufferedReaders&BufferedWriters, could you let me know?
Thanks!
When dealing with java client/server communications, if you have full control over both ends and don't anticipate designs changing, you can directly perform encoding directly using Java serialization through the Object*Stream classes.
Example:
ObjectOutputStream output = new ObjectOutputStream(bufferedSocketStream);
output.writeInt(42); // Write a primitive integer
output.writeObject("Hello World"); // Write a string as an object
output.writeObject(myClass); // Write a class instance that you've implemented the "Serialize" interface
output.flush();
/* INPUT */
ObjectInputStream inputStream = new ObjectInputStream(bis);
int value = inputStream.readInt(); // Will receive 42
Object value2 = inputStream.readObject(); // Will receive "Hello World"
Object value3 = inputStream.readObject(); // Will receive your serialized class instance
(see https://docs.oracle.com/javase/8/docs/api/java/io/ObjectOutputStream.html and https://docs.oracle.com/javase/8/docs/api/java/io/ObjectInputStream.html)
I want to connect Android Device to external device via Socket. Socket Connect to external device successfully.
Now if any data require from external device then send request of byte packet data to socket below order. if external device receive data correct then send byte data in response.
Parameters : methodname(1 byte), payloadlength(2 byte), payload(2 byte).
Now My Code is...
Socket socket = new Socket("local exteranl device ip", 5000);
if(socket.isConnected()) {
int methodname = 5;
int payload = 2151;
int payloadLength = 2;
ByteBuffer buffer = ByteBuffer.allocate(3 + payloadLength); // 3 = for method name + length
buffer.order(ByteOrder.BIG_ENDIAN); // Just to be explicit
buffer.put((byte) methodname);
buffer.putShort((short) payloadLength);
buffer.putShort((short) payload);
buffer.rewind();
byte[] result = new byte[buffer.capacity()]; // Could also use result = buffer.array();
buffer.get(result);
DataOutputStream classOUTstream = new DataOutputStream(socket.getOutputStream());
// socket is already connected
classOUTstream.write(result);
classOUTstream.flush();
InputStream stream = socket.getInputStream();
byte[] data = new byte[100];
int count = stream.read(data);
}
Above Code is Android, i knowing only basic concept of java. i am getting -1 result in count.
can any one please suggest me or tell me my mistake?
You're doing this the hard way. Get rid of the ByteBuffer altogether and use all the methods of DataOutputStream. They are all big-endian. I can't see any mistake but clearly you must be sending something the peer didn't understand so he is closing the connection instead of sending a reply.
Note: Socket.isConnected() cannot possibly be false at the point you're testing it.
I've got a server written in python running twisted (twistd), and a client written in Java. The idea is that we'll be able to send Strings of encoded data between clients via this server. However, we're finding that clients never send a string to the server (it's never logged on the server as having been received). Does anyone have any ideas?
I've included the code for the client and server below.
Client:
Socket s = new Socket("localhost", 1025);
InputStream is = s.getInputStream();
OutputStream os = s.getOutputStream();
System.out.println("Before Read");
System.out.println(is.read());
System.out.println("After Read");
os.write("Hello from java!".getBytes());
Server:
class MyChat(basic.LineReceiver):
__opponent = None
def connectionMade(self):
print "SLOG"
self.factory.clients.append(self)
print "SLOG 1"
self.factory.notInGame.append(self)
print "SLOG 2"
while (len(self.factory.notInGame) >= 2):
x = self.factory.notInGame.pop(0)
y = self.factory.notInGame.pop(0)
x.__opponent = y
y.__opponent = x
print "SLOG FINISH YAY"
def connectionLost(self, reason):
print "SLOG Lost a client!"
self.factory.clients.remove(self)
if (self.__opponent == None):
self.factory.notInGame.remove(self)
else:
self.__opponent.__opponent = None
self.factory.notInGame.append(self.__opponent)
def lineReceived(self, data):
print "SLOG Sender data received"
if self.__opponent == None:
self.transport.write("E0") # not in game
print "SLOG E0"
return
self.__opponent.transport.write(data)
from twisted.internet import protocol
from twisted.application import service, internet
factory = protocol.ServerFactory()
factory.protocol = MyChat
factory.clients = []
factory.notInGame = []
application = service.Application("chatserver")
#internet.TCPServer(1025, factory).setServiceParent(application)
reactor.listenTCP(1025, factory)
Any help appreciated - thanks
Sam
LineReceiver accumulates data in a buffer and calls the lineReceived callback when it receives a full line. By default lines are terminated by the byte sequence "\r\n".
It looks like your Java application sends "Hello from java!". Since it does not send "\r\n" LineReceiver never decides to call lineReceived.