Java Sockets - Sending data from client to server - java

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)

Related

Writing data to OutputStream without closing with CLDC

I have a small J2ME app that should send some bytes to a socket and read response. However, when I close OutputStrean, the socket closes too, and I can't read response. I thought I could try OutputStream.flush();, but it does nothing.
Here is my readAll() method that should read data from OutputStream:
public final static String readAll(InputStream d) throws IOException {
ByteArrayOutputStream res = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int length;
while ((length = d.read(bytes)) != -1){
res.write(bytes, 0, length);
}
return new String(res.toByteArray(), "UTF-8");
}
You'll typically want to have a thread running in the background that handles actually sending and receiving data.
The data that is received should provide some way of determining when that particular chunk of data terminates. For example, the server might send back:
(long)length+(byte[])data
So from the stream you would read in take 8 bytes + whatever the length is, then you would use that data to construct an object that represents that message and your other thread would read in that data to decide what data it wants to send out.
In order to send data out you would effectively do the reverse, with a separate thread consuming objects that represent messages to be sent.
These are called message queues and you can read more about them here: https://en.wikipedia.org/wiki/Message_queue

Sockets in Java - How can I write to DataOutputStream to a specific client?

I have implemented a chat using Client-Server model in Java. However, I have this one problem with dos.writeUTF(msgout) where dos is a DataOutputStream object.
Let's say Client 1 and Client 2 connect to the Server. Server is able to handle messages from both clients in its DataInputStream. However, when writing back, the server will only send the message to the last client (this case 2). The connection with Client 1 stays established, but it's like Server 'forgets' about Client 1. I do not want to broadcast, but I just want to know how can I dos.writeUTF(msgout) to e.g. the first Client? Here is my piece of code from the Server.
Static variables (i'm using Swing as GUI):
static DataOutputStream dos;
static DataInputStream dis;
static Vector<ClientHandler> ar = new Vector<>(); // Vector for active clients
static int i = 0; // Client counter
The piece from the main method where connection is settled:
ServerSocket ss = new ServerSocket(1234);
Socket s;
while (true) {
s = ss.accept();
dis = new DataInputStream(s.getInputStream());
dos = new DataOutputStream(s.getOutputStream());
ClientHandler mtch = new ClientHandler(s, "Client" + (i+1), dis, dos);
Thread t = new Thread(mtch);
ar.add(mtch); // Add client to active clients
t.start();
i++;
}
I have made a method to send messages (when I click a button):
public void send() {
try {
String msgout = "";
msgout = txtChat.getText().trim();
if (!msgout.equals("")) {
dos.writeUTF(msgout); // Need to get specific here. How to write to Client's 1 DataInputStream?
}
} catch (Exception e) {
//
}
}
ClientHandler class is found here https://pastebin.com/NWms7TfF
This is not good:
static DataOutputStream dos;
followed by:
dos.writeUTF(msgout);
You're creating a single static DataOutputStream field and then wondering why using this field only represents one output stream. First of all, you should get rid of the static fields, although this won't solve your problem (but it might help fix others). Instead if you want to write to a specific output stream, you need a way to get a reference to it. Consider creating a HashMap to hold your ClientHandler objects, and add them to the Map using whatever unique identifier you wish to use that would help you retrieve them, perhaps a clientName String field or a clientId String field (don't use numbers for id). And assuming that ClientHandler has a getDos() method that returns its output stream (if it doesn't have this then it should get one). Then you can get the ClientHandler from the Map when needed, extract its output Stream via getDos(), and then write to it.
Side note, it is not appropriate to post links to code bases. Instead please post all relevant code in your question.

Sending data from a java server in a consecutive way

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)

Communication from Java to C++ using ProtoBuf over socket

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.

Send Google Protocol buffer messages between C# and Java

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?

Categories