Socket communication between Java and C++ - java

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.

Related

How to read (all available) data from serial connection when using JSSC?

I'm trying to work with JSSC.
I built my app according to this link:
https://code.google.com/p/java-simple-serial-connector/wiki/jSSC_examples
My event handler looks like:
static class SerialPortReader implements SerialPortEventListener {
public void serialEvent(SerialPortEvent event) {
if(event.isRXCHAR()){//If data is available
try {
byte buffer[] = serialPort.readBytes();
}
catch (SerialPortException ex) {
System.out.println(ex);
}
}
}
}
}
The problem is that I'm always not getting the incoming data in one piece. (I the message has a length of 100 bytes, Im getting 48 and 52 bytes in 2 separates calls)
- The other side send me messages in different lengths.
- In the ICD Im working with, there is a field which tell us the length of the message. (from byte #10 to byte #13)
- I cant read 14 bytes:
(serialPort.readBytes(14);,
parse the message length and read the rest of the message:
(serialPort.readBytes(messageLength-14);
But if I will do it, I will not have the message in once piece (I will have 2 separates byte[] and I need it in one piece (byte[]) without the work of copy function.
Is it possible ?
When working with Ethernet (SocketChannel) we can read data using ByteBuffer. But with JSSC we cant.
Is there a good alternative to JSSC ?
Thanks
You can't rely on any library to give you all the content you need at once because :
the library dont know how many data you need
the library will give you data as it comes and also depending on buffers, hardware, etc
You must develop your own business logic to handle your packets reception. It will of course depend on how your packets are defined : are they always the same length, are they separated with same ending character, etc.
Here is an example that should work with your system (note you should take this as a start, not a full solution, it doesn't include timeout for example) :
static class SerialPortReader implements SerialPortEventListener
{
private int m_nReceptionPosition = 0;
private boolean m_bReceptionActive = false;
private byte[] m_aReceptionBuffer = new byte[2048];
#Override
public void serialEvent(SerialPortEvent p_oEvent)
{
byte[] aReceiveBuffer = new byte[2048];
int nLength = 0;
int nByte = 0;
switch(p_oEvent.getEventType())
{
case SerialPortEvent.RXCHAR:
try
{
aReceiveBuffer = serialPort.readBytes();
for(nByte = 0;nByte < aReceiveBuffer.length;nByte++)
{
//System.out.print(String.format("%02X ",aReceiveBuffer[nByte]));
m_aReceptionBuffer[m_nReceptionPosition] = aReceiveBuffer[nByte];
// Buffer overflow protection
if(m_nReceptionPosition >= 2047)
{
// Reset for next packet
m_bReceptionActive = false;
m_nReceptionPosition = 0;
}
else if(m_bReceptionActive)
{
m_nReceptionPosition++;
// Receive at least the start of the packet including the length
if(m_nReceptionPosition >= 14)
{
nLength = (short)((short)m_aReceptionBuffer[10] & 0x000000FF);
nLength |= ((short)m_aReceptionBuffer[11] << 8) & 0x0000FF00;
nLength |= ((short)m_aReceptionBuffer[12] << 16) & 0x00FF0000;
nLength |= ((short)m_aReceptionBuffer[13] << 24) & 0xFF000000;
//nLength += ..; // Depending if the length in the packet include ALL bytes from the packet or only the content part
if(m_nReceptionPosition >= nLength)
{
// You received at least all the content
// Reset for next packet
m_bReceptionActive = false;
m_nReceptionPosition = 0;
}
}
}
// Start receiving only if this is a Start Of Header
else if(m_aReceptionBuffer[0] == '\0')
{
m_bReceptionActive = true;
m_nReceptionPosition = 1;
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
break;
default:
break;
}
}
}
After writing data to serial port it need to be flushed. Check the timing and pay attention to the fact that read should occur only after other end has written. read size is just an indication to read system call and is not guaranteed. The data may have arrived and is buffered in serial port hardware buffer but may not have been transferred to operating system buffer hence not to application. Consider using scm library, it flushes data after each write http://www.embeddedunveiled.com/
Try this:
Write your data to the serial port (using serialPort.writeBytes()) and if you are expecting a response, use this:
byte[] getData() throws SerialPortException, IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] b;
try {
while ((b = serialPort.readBytes(1, 100)) != null) {
baos.write(b);
// System.out.println ("Wrote: " + b.length + " bytes");
}
// System.out.println("Returning: " + Arrays.toString(baos.toByteArray()));
} catch (SerialPortTimeoutException ex) {
; //don't want to catch it, it just means there is no more data to read
}
return baos.toByteArray();
}
Do what you want with the returned byte array; in my case I just display it for testing.
I found it works just fine if you read one byte at a time, using a 100ms timeout, and when it does time out, you've read all data in the buffer.
Source: trying to talk to an Epson serial printer using jssc and ESC/POS.

reading serial port but showing other types of character

I am reading a serial port in which there are some characters like skljdf85789^&^eeb etc..
In hyper terminal, I can see the port with normal characters.
Now, when I am reading it by using java, eclipse,
In console I should see smt like skljdf85789^&^eeb etc.. instead, I see a sequence of frequent rectangulars.
I think it is a porblem of incompatible types. I tried these:
public void serialEvent(SerialPortEvent arg0) {
int data;
switch (arg0.getEventType()) {
case SerialPortEvent.DATA_AVAILABLE:
try {
int len = 0;
int bet=0;
while ((data = in.read()) > -1) {
if (data == ' '||data == ' ' ){
break;
}
buffer[len++] = (byte) data;
}// it writes to a buffer from the port
String meterbuf = new String(buffer, 0, len);//buffer is a byte array, it casted to String here.
System.out.println("string from m485: " + meterbuf);
for(int k=0;k<meterbuf.length();k++)
{
char c=meterbuf.charAt(k);
System.out.print(Character.valueOf(c)+" ");
}// I tried to get chars one by one, it did not work, too.
Do you have any suggestions?
thanks in advance.
the problem was baudrates. I forgat to set the baudrates.
I am using c, "iar embedded systems" to write to the port and I am using Java, "eclipse" to read from the port. In both of the programs, the baudrates should be equal. if they are different, the characters would be silly:)

Stack Smashing in Java Interposer

I am writing a Java interposer to modify network communication related system calls. Basically, I want to modify the IP and port of the intended recipient.
The code works correctly on my laptop, but on university PC, it gives a stack smashing error as:
*** stack smashing detected ***: java terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0xb7702dd5]
/lib/i386-linux-gnu/libc.so.6(+0xffd8a)[0xb7702d8a]
/home/mwaqar/vibe/ldinterposer_2.so(+0x28e4)[0xb77c98e4]
/home/mwaqar/vibe/ldinterposer_2.so(connect+0x9c5)[0xb77c9093]
/usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/libnet.so(+0xceff)[0x8b226eff]
/usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/libnet.so(Java_java_net_PlainSocketImpl_socketConnect+0x4c1)[0x8b227c51]
The relevant code (interposition of connect system call) is as follows:
int connect(int fd, const struct sockaddr *sk, socklen_t sl)
{
struct sockaddr_in *lsk_in = (struct sockaddr_in *) sk;
struct sockaddr_in6 *lsk_in6 = (struct sockaddr_in6 *) sk;
struct sockaddr_in addr4;
unsigned int len;
int nbytes, oport, tport, ret, i;
char ip_address[30];
char buffer[1024];
char tempBuffer[1024];
if((lsk_in->sin_family == AF_INET) || (lsk_in->sin_family == AF_INET6))
{
if(lsk_in->sin_family == AF_INET)
{
oport = ntohs(lsk_in->sin_port);
memcpy(&addr4.sin_addr.s_addr, &lsk_in->sin_addr.s_addr, sizeof(addr4.sin_addr.s_addr));
}
else if(lsk_in->sin_family == AF_INET6)
{
oport = ntohs(lsk_in6->sin6_port);
memcpy(&addr4.sin_addr.s_addr, lsk_in6->sin6_addr.s6_addr+12, sizeof(addr4.sin_addr.s_addr));
}
memset(buffer, '\0', sizeof(buffer));
sprintf(buffer, "%s%c%s%c%i", NAT_VM_CONNECT_RULE, NAT_VM_DELIMITER, (char *)inet_ntoa(addr4.sin_addr), NAT_VM_DELIMITER, oport);
nbytes = send(sock, buffer, strlen(buffer), 0);
if(DEBUG_MODE)
fprintf(stdout, "[LD_INTERPOSER] Sent[%s]\n", buffer);
memset(buffer, '\0', sizeof(buffer));
nbytes = recv(sock, buffer, sizeof(buffer), 0);
fprintf(stderr, "[LD_INTERPOSER] Received CONNECT [%s]\n", buffer);
memset(ip_address, '\0', sizeof(ip_address));
int pos = strrchr(buffer, NAT_VM_DELIMITER) - buffer;
strncpy(ip_address, buffer, pos);
ip_address[pos] = '\0';
tport = atoi(buffer + pos + 1);
if(lsk_in->sin_family == AF_INET)
{
lsk_in->sin_addr.s_addr = inet_addr(ip_address + 7);
lsk_in->sin_port = htons(tport);
}
else if(lsk_in->sin_family == AF_INET6)
{
inet_pton(AF_INET6, ip_address, &(lsk_in6->sin6_addr));
lsk_in6->sin6_port = htons(tport);
}
fprintf(stderr, "[LD_INTERPOSER] IP[%s], Port[%d] for VM[%s]\n", ip_address, tport, vm_ip);
}
int my_ret = real_connect(fd, sk, sl);
fprintf(stderr, "Done\n");
return my_ret;
}
Here, sock is a socket that I have initialized in "constructor" of the shared library.
The program works correctly and prints Done. On the last (return) line, it gives the stack smashing error. I have no idea what is causing this.
I suspect that strrcr returns NULL in the line
int pos = strrchr(buffer, NAT_VM_DELIMITER) - buffer;
Then pos will be huge, and the following lines will read and write invalid addresses.
Always check the return value of functions (especially when they're run on data received from outside your program).
Also, as I wrote in my comment, never use sprintf. I can't tell if it fails, because I don't know what's NAT_VM_CONNECT_RULE. Even if you counted the bytes and know you're OK, you should still be careful and use snprintf instead.

java qt server/client dta transfer

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.

Reusing the inputstream of a socket

i would like to know how to keep the input stream of a socket and reuse it until the application is close.
What i do for now is creating a thread in the main method. This thread is supposed to keep running for the all time the application runs. In this thread i read data from the server using the socket input stream. But i'm able to read only one time what the server is sending. After that i think the thread is dead or i cannot read from the input stream. How can i do to keep the input stream reading what is coming from the server.
Thanks.
int length = readInt(input);
byte[] msg = new byte[length];
input.read(msg);
ByteArrayInputStream bs = new ByteArrayInputStream(msg);
DataInputStream in = new DataInputStream(bs);
int cmd = readInt(in);
switch(cmd) {
case 1: Msg msg = readMsg(cmd, msg);
}
I put here everything, but in my code things happen in different methods.
The readInt method:
public static int readInt(InputStream in) throws IOException {
int byte1 = in.read();
int byte2 = in.read();
int byte3 = in.read();
int byte4 = in.read();
if (byte4 == -1) {
throw new EOFException();
}
return (byte4 << 24)
+ ((byte3 << 24) >>> 8)
+ ((byte2 << 24) >>> 16)
+ ((byte1 << 24) >>> 24);
}
Used for little-endian conversion.
your socket might well be blocking. If you encounter such a problem one good way around is to design your software for a polling method rather than being interrupt driven. Then again, the software design pattern will be done around what you are trying to achieve.
Hope it helps! Cheers!
You need to call input.read() in a loop such as this:
try {
while(running) {
int length = readInt(input);
byte[] msg = new byte[length];
input.read(msg);
ByteArrayInputStream bs = new ByteArrayInputStream(msg);
DataInputStream in = new DataInputStream(bs);
int cmd = readInt(in);
switch(cmd) {
case 1: Msg msg = readMsg(cmd, msg);
}
}
} catch (IOException e) {
//Handle error
}
Set running to false when you are finished with what ever your thread needs to be doing. Remember input.read() will block until the socket has received something. I hope this helps.

Categories