I am trying to create a simple messaging application, using a C++ client and a Java server.
It seems I can't get around because the C++ client fails to get information from the Java server, yet I can't track down the problem.
I have tried connecting with a Java client to the Java server and it works well.
I have tried connecting with the C++ Client to a simple C++ echo server I made for this purpose, and everything is going well (it reads the information).
I have tried connecting with the java client to the c++ echo server and it works well.
Keep in mind that the Java server get all the information from the client, and is responding (eg: when I try to Log in, the server gets it, logs me in, and "sends" a http response setting the cookie and displaying a welcome message, but the client never gets it).
Here is the java code which send the reply:
while ((msg = tokenizer.nextMessage()) != null)
{
System.out.println("Received \"" + msg + "\" from client");
String response = (String)protocol.processMessage(msg);
System.out.println(response); // used for testing
if (response != null)
{
clientSocket.getOutputStream().write(response.getBytes("UTF-8"));
//the Out below this line is being initialized on connection, just put it here for you to read
//Also the out.println(response) doesn't work as well, those are 2 attempts i have made
//out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream(), "UTF-8"), true);
//out.println(response);
}
if (protocol.isEnd(msg))
{
break;
}
}
Here is the client side code (C++):
//while (_socket.available() == 0){
// boost::this_thread::sleep(boost::posix_time::milliseconds(10));
// std::cout << "test";
//}
char reply[max_length];
size_t reply_length = boost::asio::read(_socket,boost::asio::buffer(reply,10));
//size_t reply_length = boost::asio::read(_socket, boost::asio::buffer(reply, _socket.available()));
std::cout << "Reply is:\n";
std::cout.write(reply, reply_length);
std::cout << "\n";
Note that the while above in the start of the code is used in order to wait for the response after each sent message, I have tried replacing it with a longer sleep time so I wont have to check the size of the incoming buffer, as you can see just after it I am trying to read a buffer the size of 10, just from testing, and i put the "real" read line in a comment just after it.
Any help would be appreciated.
Thank you.
EDIT - Forgot to mention that if I close the socket after sending the information passes, but doing so fails the purpose, as I am trying to keep the socket open until the client performs a log out.
EDIT #2- I have tried a diffrent method of reading, by using a delimiter char and reaing the buffer 1 char at the time, it just get stuck blocking with the empty buffer.
Here is the code for the second type of reading which i have tried:
std::string respone = "";
char ch='0';
boost::system::error_code error;
try {
while(!error && ch!='$'){
size_t tmp=0;
try {
std::cout << "going to read:";
tmp = _socket.read_some(boost::asio::buffer(&ch + tmp, 1 - tmp), error);
std::cout << "finish reading 1 char";
if (error)
throw boost::system::system_error(error);
}
catch (std::exception& e) {
std::cerr << "recv failed (Error: " << e.what() << ')' << std::endl;
}
respone.append(1, ch);
}
}
A bit silly, but apparntly my anti virus was blocking all the packets from the java server (and not the c++ for some reason), turning it off solved every thing.
Related
I'm porting some C# code to Java code and I done it right (hopefully) but I'm still clueless on the behaviour or what I do miss on the Java port.
Background: It's a server socket reading & sending packets (as a byte[]). I have no access to the client layer, but the structure is right on the server side (so the client can accept)
C# code uses NetworkStream to write/read.
Java code uses InputStream & OutputStream to write/read.
C# code: (the thread method is started via Thread.start)
public override void ReceivingThread(object o)
{
Client client = (Client)o;
PacketStream clientStream = client.PacketStream;
byte[] clientBuffer = new byte[4096];
packetHandler.SendFirstPacket(client);
while ((!this.Stopped) && (clientStream.Read(clientBuffer, 0, 8) != 0))
{
if (BitConverter.ToInt16(clientBuffer, 6) > 0)
{
clientStream.Read(clientBuffer, 8, BitConverter.ToInt16(clientBuffer, 6));
}
Packet packet = new Packet(clientBuffer);
Console.WriteLine($"RECV [{packet.PacketId:X4}] {BitConverter.ToString(packet.GetRawPacket(), 0, packet.DataLength + 8)}");
packetHandler.HandlePacket(client, packet);
}
Console.WriteLine("outside of loop");
}
Scenario: Server sends first packet, client reads it and sends credentials(in this case), server checks them. To make it easier for now I send a packet with a code indicating that credentials are invalid (code -4 as a short -> 4002). The client accepts it immidiatly and the Thread is discarded. (the "outside of loop" is hit). The client doesn't hang, nor does the server.
I replicated or better to say, ported that code and functionality in Java.
Since in Java you cannot start Threads as methods in form of Thread extending etc. I'm starting the thread with help of Java8 & lambdas. (new Thread(() -> receivingThread(client)).start();)
#Override
public void receivingThread(Object o) {
Client client = (Client) o;
PacketStream clientStream = client.getPacketStream();
byte[] clientBuffer = new byte[4096];
packetHandler.sendWelcomePacket(client);
while ((!this.stopped) && (clientStream.read(clientBuffer, 0, 8) != -1)) {
if (BitKit.bytesToShort(clientBuffer, 6) > -1)
clientStream.read(clientBuffer, 8, BitKit.bytesToShort(clientBuffer, 6));
Packet packet = new Packet(clientBuffer);
logger.info("RECV [" + String.format("0x%x", (int)packet.getPacketId()) + "] " + BitKit.toString(packet.getRawPacket(), 0, packet.getDataLength() + 8));
packetHandler.handlePacket(client, packet);
}
logger.info("outside of loop");
}
NetworkStream.Read returns 0, Java InputStream.read returns -1 for eof.
The thing is, in the Java port, it hangs after the second packet is sent. Like somehow the read blocks in some not normal way. I think it's about a minute or something. Then the client throws an connection error instead of the code I sent with the second write.
The streams are setup in constructor of Client class which is passed down. The write and read operations are for raw data -> read(byte[] buffer, int offset, int size)
Any ideas about it?
Why does it work on C# end and not Java? Does C# work with packets differently than Java? Any help is appreciated and thanks in forward!
P.S: Sorry for the long text :)
I have a socketserver set up with a remote client, and it is functional. Upon opening the client and logging in, I noticed that sometimes, there is an error that seems to be due to the client reading an int when it shouldn't be.
Upon logging on, the server sends a series of messages/packets to the client, and these are anything from string messages to information used to load variables on the client's side.
Occasionally, while logging in, an error gets thrown showing that the client has read a packet of size 0 or a very large size. Upon converting the large-sized number into ascii I once found that it was a bit of a string "sk." (I located this string in my code so it's not entirely random).
Looking at my code, I'm not sure why this is happening. Is it possible that the client is reading an int at the wrong time? If so, how can I fix this?
InetAddress address = InetAddress.getByName(host);
connection = new Socket(address, port);
in = new DataInputStream(connection.getInputStream());
out = new DataOutputStream(connection.getOutputStream());
String process;
System.out.println("Connecting to server on "+ host + " port " + port +" at " + timestamp);
process = "Connection: "+host + ","+port+","+timestamp + ". Version: "+version;
write(0, process);
out.flush();
while (true) {
int len = in.readInt();
if (len < 2 || len > 2000) {
throw new Exception("Invalid Packet, length: "+len+".");
}
byte[] data = new byte[len];
in.readFully(data);
for (Byte b : data) {
System.out.printf("0x%02X ",b);
}
try {
reader.handlePackets(data);
} catch (Exception e) {
e.printStackTrace();
//connection.close();
//System.exit(0);
//System.out.println("Exiting");
}
}
//Here is code for my write function (Server sided):
public static void write(Client c, Packet pkt) {
for (Client client : clients) {
if (c.equals(client)) {
try {
out.writeInt(pkt.size());
out.write(pkt.getBytes());
out.flush();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
So looking at the write function, I don't really see how it could be confusing the client and making it read for the size of the packet twice for one packet (at least that's what I think is happening).
If you need more information please ask me.
The client side code looks fine, and the server side code looks fine too.
The most likely issue is that this is some kind of issue with multi-threading and (improper) synchronization. For example, maybe two server-side threads are trying to write a packet to the same client at the same time.
It is also possible that your Packet class has inconsistent implementations of size() and getBytes() ... or that one thread is modifying a Packet objects while a second one is sending it.
I'm writing a C++ that has a feature of receiving file via socket from a Java client.
The file's size I'm trying to send is 510KB, but the server only receives 46KB and then gets stuck "waiting" for more bytes.
This is the server code: (I tried to receive 510KB at once, but the server got stuck, so I tried also to receive 64KB each iteration and again, the server got stuck).
int bytes_to_receive;
size_t length;
while(file_length > 0)
{
if(file_length >= 65536)
bytes_to_receive = 65536;
else
bytes_to_receive = file_length;
char buf5[bytes_to_receive];
length = 0;
while( length < bytes_to_receive )
length += socket.read_some(boost::asio::buffer(&buf5[length], bytes_to_receive - length), error);
string temp(buf5);
file_parts.push_back(temp);
file_length -= bytes_to_receive;
}
string file("");
vector<string>::const_iterator it;
for(it = file_parts.begin(); it != file_parts.end(); ++it)
{
file += *it;
}
The Java client load the file to a string, and then sends the string using
writeBytes
Note: When sending a 1KB file everything works.
Why does this happens and how can I fix it? Any help would be highly appreciated.
Edit: any other way of receiving large data using boost would be appreciated.
EDIT I have it working now thanks to the comments below. I also explained what I fixed in the comments. Thanks for the help guys.
Im working on a multiplayer game in java. It's coming along pretty well so far, but Im having an issue with the server sending information to the client. The process should be that, the server receives information from the client and interprets what it's supposed to do. In this case, the client sends a chat message to the server split with commas. "chat,Bob,the message is here."
At this point in time, the server should essentially send back that same information to the client that sent the message. Somehow, along the way though, the ByteBuffer which is what is housing the information gets corrupted?
The following is the pertinent code for the server:
// Read the data
SocketChannel sc = (SocketChannel) key.channel();
// interpret
int bytesEchoed = 0;
while (true) {
//Clears this buffer.
echoBuffer.clear();
int number_of_bytes;
String message = new String(echoBuffer.array());
String[] splits = message.split(",");
try {
number_of_bytes = sc.read(echoBuffer);
} catch (java.io.IOException e) {
key.cancel();
number_of_bytes = -1;
}
//-----------Interpret Packets--------------------
//-------------Chat-----------------
if (splits[0].contentEquals("chat")) {
//do chat shit
String name = splits[1];
String text = splits[2];
String sendBack = "chat," + name + "," + text + ","+"\r";
System.out.println(sendBack);
if (splits[0].equals("chat")) {
echoBuffer.clear();
echoBuffer.put(sendBack.getBytes());
}
}
//
if (number_of_bytes <= 0) {
break;
}
//
//
echoBuffer.flip();
sc.write(echoBuffer);
bytesEchoed += number_of_bytes;
}
System.out.println("Echoed " + bytesEchoed + " from " + sc);
// once a key is handled, it needs to be removed
it.remove();
}
}
}
}
Can anyone tell me what I am messing up?
I wasn't doing clear() before I was putting the sendBack string to the bytebuffer, and that was adding the text to the end of the buffer, instead of the beginning. Also, on the client side I was using readLine() to get the incoming data, but there was no carriage return "\r" or new line "\n" on the outgoing server data, resulting in my client reading nothing. Those two things fixed, have it working properly.
On the one side of the socket I know the data is going into the socket correctly.
I set up a connection:
Connection sr = new Connection();
Server server = new Server("NAME", Interger.parseInt(port));
server.setIp(ip);
sr.setServer(server);
//I know my server connection code is correct because I can send and receive data in
//other areas of my program just fine
InputStream is = null;
try
{
is = sr.getChannel().socket().getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuffer text = new StringBuffer();
int k =0;
while(k != -1)
{
k = br.read();
text.append((char) k);
}
}
catch(Exception e)
{
//no errors ever get thrown
}
And then I only get about half my data, 10989 bytes out of a total 21398 that I send. The amount of bytes it reads varies but the data always ends with ..., "values": [" which in the data I send over looks like , ..., "values": ["", ""].
Keep reading until you have all the data. This question has been showing up about once a week lately. There's no guarantee that the network is going to have all your data show up at once.
You need to keep reading until you have all your data. How do you know how much data was sent? You should probably build a little protocol between the client/server that defines how much data is going to be sent, the server reads that little header and continues to read until the full message has been received.
Don't know if this could help you :
int k =0;
while((k = br.read()) != -1){
text.append((char) k);
}
1) In your case it is making the check on the next iteration, which may lead to appending of non-representable character(char of -1) to the end of text.
2) Never leave catch block empty, may be there is some execption.
So because my sending side of the socket was in c++ I was accidentally passing in a null ASCII value into the socket. And it is undocumented on the java side of the socket that if the read encounters a null value it treats it as an end of file. So it was prematurely ending the stream because it hit the null.