java qt server/client dta transfer - java

I created a client (created by JAVA) and a server (by qt/c++), but I have a data transfer problem (something wrong with format I think).
The server side code:
void Pirate::DateArrived()
{
QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
QDataStream in (socket);
qDebug()<< socket->bytesAvailable();// here it give me the number of chars i sent in this ex:3
QString cmd ;
in >> cmd;
qDebug()<< cmd.size(); // here it always stay 0
qDebug() << cmd; // always ""
}
public void SendData(String data) throws IOException
{
OutputStream theOutput = socket.getOutputStream();
OutputStreamWriter out = new OutputStreamWriter(theOutput);
out.write("abc");
out.flush();
}

According to the docs, when you deserialize a QString, it is expected that the data will consist of the string length in bytes (quint32) followed by the data in UTF-16.

Related

UDP datagram Socket Programming with server in JAVA and Client in C++

Below is the code for client server communication using UDP datagram protocol with server in JAVA and Client in cpp.
The task of the server is to read the data received from the client on its port and then unpack the string.
Now using String Builder we want to write that in the output file.
The problem which we are facing is that the output in the file is
javac UDPServer.java | On terminal2 Running gcc -g client.cpp -o client
java UDPServer | On terminal2 Running ./client
56,abcde^#,orange1
However the correct output should be
56,abcde,orange1
Also, pls check for closing of the file objects such as fo.close() and fw.close(), we have used finally block; Is that a good idea to close file descriptor objects?? Or shall we need to use some other techniques to close the file descriptor objects??
Below is the code for server:
import java.io.*;
import java.net.*;
import java.util.regex.*;
class UDPServer {
public static void main(String args[]) throws Exception
{
FileOutputStream fo = new FileOutputStream("OUTFILE.txt",true);
PrintWriter pw = new PrintWriter(fo);
StringBuilder sb= new StringBuilder();
DatagramSocket serverSocket = new DatagramSocket(11111);
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
try{
while(true)
{
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
String sentence = new String(receivePacket.getData());
System.out.println("RECEIVED: " + sentence);
InetAddress IPAddress = receivePacket.getAddress();
int port = receivePacket.getPort();
System.out.println("Got packet form address:" +IPAddress);
String capitalizedSentence = sentence.toUpperCase();
if (receivePacket != null && receivePacket.getLength() != 0) {
String result = new String(receivePacket.getData());
result = result.trim(); // remove leading and trailing whitespaces...
String match_pattern="(\\d+)(a.*)(y.*)";
//create a pattern object
Pattern regexp_patternobject= Pattern.compile(match_pattern);
//create a matcher object
Matcher m_obj= regexp_patternobject.matcher(result);
if (m_obj.find()){
System.out.println("Found Value: " +m_obj.group(0) );
System.out.println("Found Value: " +m_obj.group(1) );
System.out.println("Found Value: " +m_obj.group(2) );
System.out.println("Found Value: " +m_obj.group(3) );
sb.append(m_obj.group(1));
sb.append(',');
sb.append(m_obj.group(2));
sb.append(',');
sb.append(m_obj.group(3));
sb.append('\n');
System.out.println("StringBuilderValue: " +sb);
pw.write(sb.toString());
}
else
{
System.out.println("Matching Pattern Not Found");
}
pw.write(sb.toString());
}
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
finally{
pw.close();
fo.close();
}
}
}
Your C program is sending a stream of bytes representing the contents of a struct ssi_dump_nmsdata_type instance.
typedef struct {
char rssi;
unsigned char bssid[6];
char ssid[16];
} ssi_dump_nmsdata_type;
The bssid field is a 6-byte array of unsigned char, and in the instance you show the value is abcde in the first 5 bytes with the last byte being 0x00. In C that would be taken as the end-of-string character and not printed. Strings in Java are not null-terminated so that character is being printed.
You need to change the code in Java that unpacks the struct to better cope with the possibility of one or more trailing null bytes (0x00) in the bssid and ssid fields. Regular expressions are a bad idea here, and what you've got so far will fail as soon as you receive a BSSID that doesn't start with a or an SSID that doesn't start with y.
You should first split up the buffer based on character count (1, 6 and 16 bytes) and then remove any trailing null bytes from BSSID and SSID.
However you should be aware that what you are doing glosses over some important and subtle details. When you do (in Java)
String result = new String(receivePacket.getData());
The received data is being decoded from a byte stream to a Java Unicode character string using the default encoding. If the stream contains non-ASCII byte values (outside the range 0x00-0x7f) you may get unexpected results. Explaining all the ramifications in detail is beyond the scope of what SO is intended for.
You should investigate and learn about the difference between a byte stream (what you C program is sending) and a Java String. You should be splitting up the fields of the struct from the byte stream first, as bytes, before converting them to Java String instances. The buffer classes in java.nio are intended for just this purpose, so I recommend you follow some tutorials on "Java NIO Buffers".
UDPServer.java has no problem .
the problem comes from cpp client.
I recommend you to fix like this:
bssid length: from 6 to 5.

Why is some of my socket data getting overwritten with "3f" bytes?

I am using: Android Studio/Java 1.8 (Client) VS2010/.NET 4.0 (Server)
This Java code is constantly sending invalid data:
long FileSize = 1131666;
byte [] fs = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN).putLong(FileSize).array();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write("FILE".getBytes());
baos.write(fs); //HERE
baos.write(GetHash().getHexStdstring().getBytes());
baos.write(dest_filename.getBytes());
OutputStream out = socket.getOutputStream();
out.write(baos.toByteArray());
out.flush();
This is what I get (viewed with wireshark):
46:49:4c:45: ("FILE")
3f:44:11:00:00:00:00:00: (1131583)
32:37:64:35:36:61:32:34:32:36:31:30:37:36:37:32:30:65:34:38:66:37:34:65:36:61:64:38:34:65:36:30:65:64:33:63:66:64:34:36:32:64:36:62:37:65:62:64:62:32:63:63:62:37:37:64:36:38:37:66:64:64:66:39:
5c:45:75:72:6f:70:65:2e:70:6e:67
And thus my C++ server app receives the value as 1131583, but no matter what value I use as FileSize, I always seem to get a 3f in there somewhere...
Another instance is when the FileSize is 22451663, I get 3f:3f:56:01:00:00:00:00 (or 22429503).
Any thoughts?
Weird thing is, if I translate fs back to a number or a string and Toast the value, just before it's sent, it says its correct.
6:49:4c:45: ("FILE")
00:00:00:00:00:11:44:3f: (1131583)
Cannot reproduce, and 00:00:00:00:00:11:44:3f: is not a little-endian representation of 1131583. It is a big-endian representation of 1131583. As a little-endian number it is a rather large number: 4347598471168.
What this code actually produces on the wire, as printed by
ByteArrayOutputStream baos = new ByteArrayOutputStream()
{
public void write(byte[] bytes) throws IOException
{
for (byte b : bytes)
{
System.out.print(Integer.toHexString(b & 0xff)+":");
}
System.out.println();
super.write(bytes);
}
};
is:
46:49:4c:45:
92:44:11:0:0:0:0:0:
// etc.
There is no problem with this code.
So, the ISO-8859-1 character for 0x3f is ?, and it seems that because I was sending my constructed ByteArayOutputStream to my Send(String string) function, it was changing a lot of bytes to 0x3f, like 0x92 which has no ISO-8859-1 character.
I changed my code to like so:
// in main code
Bytestring message = new Bytestring(baos.toByteArray());
Send(message);
// send function
public void Send(Bytestring string) {
OutputStream out = socket.getOutputStream();
// other code for writing header
out.write(string.getBytes());
out.flush();
}
Bytestring being a string class I created based on a byte array, instead of a String which is based on a (2-byte) char array.

Send Byte array then String then Byte over socket Java

I need to send a text message to server over Java socket and then to send a byte array and then a string etc...
What I've developed until now is working but the client manages to read only the first string that has been sent.
From the server side: I send byte array using BufferedOutputStream, and PrintWriter to send string.
The problem is that the client and the server are not synchronized, I mean the server send string then byte array then string without waiting for the client to consume each needed byte.
I mean the scenario is NOT like this:
Server Client
Send String read String
Send byte read byte
But it is like this:
Server Client
Send String
Send byte
Send String
Send byte
read String
read byte
read String
read byte
Something that could be useful is that I know exactly the size of each string and each byte array to be read.
Here is the methods used to send string and byte array respectively:
// Send String to Client
// --------------------------------------------------------------------
public void sendStringToClient (
String response,
PrintWriter output) {
try {
output.print(response);
output.flush();
} catch(Exception e) {
e.printStackTrace();
}
System.out.println("send Seeder String : " + response);
}
// Send Byte to Client
// --------------------------------------------------------------------
public void sendByteToClient (
byte[] response,
BufferedOutputStream output) {
try {
output.write(response, 0, response.length);
//System.out.println("send : " + response);
} catch (IOException e) {
e.printStackTrace();
}
}
Here is the methods used to read string and byte array respectively:
public byte[] readInByte(int size) {
byte[] command = new byte[size];
try {
this.inByte.read(command);
} catch (IOException e) {
e.printStackTrace();
}
return command;
}
public String readInString(int size) {
char[] c = new char[size];
try{
this.inString.read(c, 0, size);
} catch (IOException e) {
e.printStackTrace();
}
return String.valueOf(c);
}
Something that could be useful is that i know exactly the size of each string to be read and each byte array to be read.
Exactly. That's very common. Basically you length-prefix each message - and you might want to provide more header information than that (is it a string or a byte array message, for example).
You could represent the message length (always in bytes) either as a fixed number of bytes (e.g. 4, assuming you never need more than 4GB messages) or use a 7-bit encoded integer (where you send 7 bits of the length in each byte, and the top bit just indicates whether this is the last byte of the length or not).
Once you've got message lengths, you're basically set - you've effectively divided the stream of data into self-describing blocks. Job done.
(As an aside, I'd avoid using PrintWriter due to its exception-swallowing nature. You won't actually need the writer once you're doing this though, as you'll probably want to convert each String into a byte array anyway, to count its length in bytes before you send it. Remember to specify the encoding!)
I'd be really tempted to convert the data to JSON format and pipe it over http. You get a ton of benefits including ready made http servers and clients for just about every platform on earth along with the JSON interop not to mention all the built in error handling and recovery processing.
The drawbacks would be the additional overhead of http and the JSON encoding. You didn't mention if this was a UDP or TCP socket so that could be an additional drawback if you were trying to go connectionless.

Socket communication between Java and C++

I'm trying to have a connection between a Java server and a C++ client. But when I read the data in my client I always have the same strange character (’). I tried to change the encoding in both side but nothing work.
Here is my Java code :
public class Serveur
{
public static void main(String[] args) throws Exception
{
final int PORT = 13370;
try
{
ServerSocket service= new ServerSocket(PORT);
Socket connection = service.accept();
PrintWriter pw = new PrintWriter(connection.getOutputStream());
String s = Integer.toString(5);
while(true)
{
pw.print(s.getBytes("UTF-8"));
pw.flush();
pw.close();
}
connection.close();
}
}
I also tried to use an OutputStream, a DataOutputStream and a BufferedOutputStream.
And here is the C++ code :
int main(int argc, char* argv[])
{
WSADATA WSAData;
WSAStartup(MAKEWORD(2,0), &WSAData);
SOCKET sock;
SOCKADDR_IN sin;
char buffer[512];
sin.sin_addr.s_addr = inet_addr("127.0.0.1");
sin.sin_family = AF_INET;
sin.sin_port = htons(13370);
sock = socket(AF_INET,SOCK_STREAM,0);
if(connect(sock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR)
{
cout<<"connection"<<endl;
if(recv(sock, buffer, sizeof(buffer), 0) != SOCKET_ERROR)
{
string s = buffer;
wchar_t *pwchello = L"Hi";
wchar_t *pwc = (wchar_t *)malloc( sizeof( wchar_t ));
char *pmbhello = buffer;
int i = mbstowcs(pwc,pmbhello, MB_CUR_MAX);
cout << i << endl;
cout<<"cout : "<<pwc<<endl;
cout <<buffer<<endl;
printf("printf : %s\n", buffer);
cout << "wsagetlasterror() : "<<WSAGetLastError();
closesocket(sock);
WSACleanup();
free(m_pBuffer);
}
return 0;
}
As you can see, I tried different solution but without success.
Thanks in advance, and sorry for my english it may be not very good
You are mixing up lots of different encoding conversions and I/O strategies. You should try out the following simplified version:
if(connect(sock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR)
{
cout << "connection" << endl;
// the result of 'recv()' is either SOCKET_ERROR or
// the number of bytes received. don't though away
// the return value.
const int result = recv(sock, buffer, sizeof(buffer), 0);
if(result != SOCKET_ERROR)
{
// use length (in bytes) returned by 'recv()'
// since buffer is not null terminated.
string s(buffer,result);
// 's' is in UTF-8 no converstion to wide strings
// should be necessary.
cout << "message: '" << s << "'." << endl;
}
closesocket(sock);
}
WSACleanup();
However, note that the standard output is in the current code page and usually UTF-8 is not the default code page. Outputing Unicode data to the console in windows requires a few other library calls to configure.
recv does not turn its destination buffer into null-terminated string. It fills in a number of bytes in the buffer, but does not append a 0.
You need top do this (with error checking, of course):
ssize_t bytesRead = recv(buffer, ...);
string str(buffer, bytesRead);
Also, be aware that recv does not guarantee that something sent in one call gets received in one call (unless you're doing UDP).
You're only allocating room for a single wchar_t here:
wchar_t *pwc = (wchar_t *)malloc( sizeof( wchar_t ));
You also assign buffer to string s, but never seem to use s
I have been having the same problem since last night. Finally figured out that encoding is not recognized by my server (written in C). Therefore, I changed in my client
someOutputStream.writeUTF(someSillyString);
to
someOutputStream.write(someSillyString.getBytes());
This way, I did not even need to typecast on the server side.

Sending an int from Java to C using sockets

I was just wondering how to send an int from a Java application to a C application using sockets. I have got different C programs communicating with each other and have got the Java application retrieving data from the C application, but I can't work out sending.
The C application is acting as database, the Java application then sends a user id (a 4 digit number) to the C application, if it exists it returns that record's details.
In Java I have tried using a printWriter and DataOutputStream to send the data, printWriter produces weird symbols and DataOutputStream produces "prof_agent.so".
Any help would be appreciated as I don't have a good grasp of sockets at the moment.
You can use DataOutputStream.writeInt. It writes an int already in network byte order by contract.
On a C side you can call recv, or read to fill in the 4-byte buffer, and then you can use ntohl ( Network-TO-Host-Long ) to convert the value you've just read to your platform int representation.
You can send the textual representation. So the number 123 would be sent as 3 bytes '1' '2' '3'.
It's a bit too late but let this answer be here. Using UDP sockets:
Java code:
public void runJavaSocket() {
System.out.println("Java Sockets Program has started."); int i=0;
try {
DatagramSocket socket = new DatagramSocket();
System.out.println("Sending the udp socket...");
// Send the Message "HI"
socket.send(toDatagram("HI",InetAddress.getByName("127.0.0.1"),3800));
while (true)
{
System.out.println("Sending hi " + i);
Thread.currentThread();
Thread.sleep(1000);
socket.send(toDatagram("HI " + String.valueOf(i),InetAddress.getByName("127.0.0.1"),3800));
i++;
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
public DatagramPacket toDatagram(
String s, InetAddress destIA, int destPort) {
// Deprecated in Java 1.1, but it works:
byte[] buf = new byte[s.length() + 1];
s.getBytes(0, s.length(), buf, 0);
// The correct Java 1.1 approach, but it's
// Broken (it truncates the String):
// byte[] buf = s.getBytes();
return new DatagramPacket(buf, buf.length,
destIA, destPort);
}
C# code:
string returnData;
byte[] receiveBytes;
//ConsoleKeyInfo cki = new ConsoleKeyInfo();
using (UdpClient udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3800)))
{
IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3800);
while (true)
{
receiveBytes = udpClient.Receive(ref remoteIpEndPoint);
returnData = Encoding.ASCII.GetString(receiveBytes);
Console.WriteLine(returnData);
}
}
Try this:
Socket s = ...;
DataOutputStream out = null;
try {
out = new DataOutputStream( s.getOutputStream() );
out.writeInt( 123456 );
} catch ( IOException e ) {
// TODO Handle exception
} finally {
if ( out != null ) {
try {
out.close();
} catch ( IOException e ) {
// TODO Handle exception
}
}
}
It whould help if you could explain a little more what your problem is.

Categories