Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Работа с сетью > Socket C++ <=> Java


Автор: Temdegon 23.10.2010, 01:40
Есть windows-приложение, с которым мне нужно общаться из джава. Каких-то встроенных возможностей для коммуникации в нем не предусмотрено, но есть возможность загуржать пользовательскую dll, чем я и воспользовался. Написал свою dll на c++ и из нее коннекчусь к своему java-серверу. В сях я нуб, по этому сильно не заморачивался, нашел готовую реализацию сокета
http://www.adp-gmbh.ch/win/misc/sockets.html
и вроде пока все получается. Строки передаются и принимаются без проблем. Но одними строками сыт не будешь. Мне надо из этой dll в джава передать вот такую структуру:
Код

struct holdem_player{
    char            m_name[16]          ;    
    double          m_balance           ;    
    double          m_currentbet        ;    
    unsigned char   m_cards[2]          ;    
    unsigned char   m_name_known    : 1 ;
    unsigned char   m_balance_known : 1 ;
    unsigned char   m_fillerbits    : 6 ;    
    unsigned char   m_fillerbyte        ;
};

struct holdem_state{
    char            m_title[64]         ;    
    double          m_pot[10]           ;    
    unsigned char   m_cards[5]          ;    
    unsigned char   m_is_playing    : 1 ;    
    unsigned char   m_is_posting    : 1 ;    
    unsigned char   m_fillerbits    : 6 ;    
    unsigned char   m_fillerbyte        ;    
    unsigned char   m_dealer_chair      ;    
    holdem_player   m_player[10]        ;    
};


Как это правильнее (и просто, если это применимо к си smile ) сделать?
Еще меня настораживает один момент. Как-то странно выглядит функция для отправки байтов:

Код

// метод отправки строки, работает
void Socket::SendLine(std::string s) {
  s += '\n';
  send(s_,s.c_str(),s.length(),0);
}
// вроде для отправки байт, но опчему-то обьявлен как string, и не особо отличается от SendLine
// это нормально?
void Socket::SendBytes(const std::string& s) {
  send(s_,s.c_str(),s.length(),0);
}


Как мне отправлять такие данные в в этот метод, и как их потом использовать в джава?

Автор: EgorTheBlade 23.10.2010, 12:04
Никогда до етого такую функцию не видел в С++ для отправки байт.
Переконвертируте ваши данные в байты в ручную или исп http://stackoverflow.com/questions/105252/how-do-i-convert-between-big-endian-and-little-endian-values-in-c.

Автор: COVD 23.10.2010, 14:02
Цитата

Как-то странно выглядит 

Это и есть одна из причин появления на свет Java.

Цитата

как их потом использовать в джава

Читайте по-байтно и укладывайте в ByteBuffer. А потом извлекайте из ByteBuffer примитивные java-аналоги методами типа getDouble(), get() (для byte).... Для правильной интерпретации целочисленных типов int, long возможно надо установить в ByteBuffer порядок байтов ByteOrder.LITTLE_ENDIAN. 

Автор: Temdegon 24.10.2010, 04:22
Спасибо. Подозревал, что так и придется делать, но решил спросить на всякий случай. Думал, может через json передавать данные. Но я так понял, там возни будет не меньше. 

Автор: kosmonaFFFt 25.10.2010, 11:12
Можно через XML, на Java оно очень просто парсится...

Автор: casey 31.10.2010, 17:14


Код

void Socket::SendBytes(const std::string& s) {
  send(s_,s.c_str(),s.length(),0);
}


Функция будет некорректно работать в случае нахождения в последовательности байт к отправке байта 0х00  - проверил на VC++ 2008. Да тут и так ясно что так не следует делать - нужно переписать типа так:

Код

void Socket::SendBytes(const char *bytebuffer,int lengthofbuffer) {
  send(s_,bytebuffer,lengthofbuffer,0);
}





Автор: Amp 1.11.2010, 11:23
Цитата(casey @  31.10.2010,  17:14 Найти цитируемый пост)
Функция будет некорректно работать в случае нахождения в последовательности байт к отправке байта 0х00  - проверил на VC++ 2008

Каким же образом ты это проверил?

Автор: casey 1.11.2010, 12:20
Код

#include "stdafx.h"
#include <string>


using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
string str;
str = "iii\0jjj";
cout << str << "\n";
cout << str.length() << "\n";
str+="\0rrr";
cout << str << "\n";
cout << str.length() << "\n";

    return 0;
}


Так устроит?

Результат соответственно:

Код

iii
3
iii
3

Автор: Amp 1.11.2010, 15:14
А причем здесь обсуждаемая функция? smile Вся загвоздка в инициализации строки, которая в нее передается. Если хочется положить туда некие нестроковые данные, то не надо явно или косвенно вызывать методы, которые повязаны на null-terminated логике.

Код

char buffer[] = {"iii\0jjj"};
std::string str(buffer, sizeof(buffer));

std::cout << str.length() << std::endl;


Либо так
Код

str.resize(sizeof(buffer));
memcpy((void *)(str.c_str()), buffer, sizeof(buffer));


Добавлено через 2 минуты и 50 секунд
Конечно в описываемом случае работа со строкой является некрасивым решением.

Автор: casey 1.11.2010, 15:58
Код

char buffer[] = {"iii\0jjj"};
std::string str(buffer, sizeof(buffer));

std::cout << str.length() << std::endl;


Согласен, не знал что так можно обойти


Код

str.resize(sizeof(buffer));
memcpy((void *)(str.c_str()), buffer, sizeof(buffer));


Так по идее нельзя, потому как
const char* c_str()
Вобщем-то это костыль, который не обязан везде работать

Автор: Amp 1.11.2010, 16:41
Цитата(casey @  1.11.2010,  15:58 Найти цитируемый пост)
const char* c_str()
Вобщем-то это костыль, который не обязан везде работать 

Да вся эта история со string по сути костыль.

Автор: Temdegon 2.11.2010, 16:35
Я поступил самым примитивным способом - сбросил все данные в строку через разделитель.
Всем спасибо

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)