Повторно использовать сокет несколько раз для отправки и получения строк / байтов между C ++ и Java

Я пытаюсь повторно использовать один и тот же сокет для отправки и получения строк (и / или байтов) между клиентом C ++ и сервером Java (или наоборот). Я могу повторно использовать сокет в том смысле, что я могу отправлять (один раз) из Java и получать (один раз) из C ++ и делать то же самое наоборот (отправлять из C ++ в Java). Однако, если я попытаюсь отправить на Java из C ++ более одного раза, второй (String или byte) не придет. Для случая String (отправка массива char из C ++) я всегда получаю нулевое значение. Обратите внимание, что у меня нет этой проблемы при обмене данными между C ++ и C ++ или Java и Java с одним и тем же кодом. Я знаю, что BufferedInputReader нужна новая строка. Для байтов я получаю IndexOutOfBound. Смотрите ниже код. Java сервер ->

 // in main...
TCP tcp = new TCP();
tcp.sendStr("Send File");
String x = tcp.recvStr();
System.out.println(x);
x = tcp.recvStr();
System.out.println(x);
//issue starts from here
x = tcp.recvStr();
System.out.println(x);

//.... IN TCP CLASS
// Global class variables in TCP
ServerSocket serverSocket = new ServerSocket(8080);
serverSocket.accept(); // this is done somewhere in the class
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);

public String recvStr(){

String msg = null;

try {
msg = br.readLine();
}catch (Exception e) {
e.printStackTrace();
}

return msg;
}

public void sendStr (String msg) {

try {

pw.write(msg);
pw.flush();
}

catch (Exception e) {
e.printStackTrace();
}
}

Клиентский код C ++

 //.. main thread of execution
struct sockaddr_in server_address, client_addr;
memset(&server_address, '0', sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = INADDR_ANY;
server_address.sin_port = htons(PORT);
TCP tcp;
char receiveBuffer[1024] = {};

int server_fd = 0,  new_socket = 0;

tcp.RecieveChar(server_address, receiveBuffer, new_socket);

std::cout << receiveBuffer << std::endl;

char chunkSize[64] = "yeahh!\n";

tcp.SendChar(server_address, chunkSize, new_socket, server_fd);

char chunk[128] = "weeeee\n";

tcp.SendChar(server_address, chunk, new_socket, server_fd);

//... in class tcp

template<int SIZE>
void TCP::SendChar(struct sockaddr_in server_addr, const char (&data)[SIZE], int &socket_id, bool close_connection ){

int opt = 1;
int addrlen = sizeof(server_addr);
int server_accept;

// Creating socket file descriptor
// Create one if only one does not exist
if(socket_id == 0){
if ((socket_id = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
std::cerr << "Error in creating socket" << std::endl;
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 8080
if (setsockopt(socket_id, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
&opt, sizeof(opt)))
{
std::cerr << "Error in setting socket" << std::endl;
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port
if (bind(socket_id, (struct sockaddr *)&server_addr,
sizeof(server_addr))<0)
{
std::cerr << "Error in binding socket" << std::endl;
exit(EXIT_FAILURE);
}
if (listen(socket_id, 3) < 0)
{
std::cerr << "Error in accepting listening" << std::endl;
exit(EXIT_FAILURE);
}
if ((server_accept = accept(socket_id, (struct sockaddr *)&server_addr,
(socklen_t*)&addrlen))<0)
{
std::cerr << "Error in accepting connection" << std::endl;
exit(EXIT_FAILURE);
}
socket_id = server_accept;
}sendto(socket_id, data, SIZE, 0, (struct sockaddr*) &server_addr, sizeof(server_addr)); // need to change to client address?

}

void TCP::RecieveChar(struct sockaddr_in server_addr, char *received_data,
int &socket_address_binder, bool close_connection){
int valread;

if(socket_address_binder == 0){
if ((socket_address_binder = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
std::cerr << "\n Socket creation error" << std::endl;
}

if (connect(socket_address_binder, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
{
std::cerr << "\nConnection Failed \n" << std::endl;
}
}

valread = read( socket_address_binder , received_data, 1024);

if(valread == 0){
std::cerr << "Error in read" << std::endl;
}
std::cout << "Received: " << received_data << std::endl;
}

Обратите внимание, что я включил код для отправки и получения массива символов / строк. Я также могу отправить файл между двумя без проблем, однако, когда я пытаюсь повторно использовать сокет после получения строки в Java, я получаю следующую ошибку:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
at java.lang.System.arraycopy(Native Method)
at java.io.BufferedOutputStream.write(BufferedOutputStream.java:128)

0

Решение

Я выяснил, что является причиной проблемы, однако я не знаю, почему это вызывает проблему. Проблема заключается в том, что я использую массивы C char, а массив char добавляет нулевой символ в конец массива. Как только BufferedReader получает Null из потока, он просто видит все остальное как NULL. Я не знаю, почему он так себя ведет. Я нашел исправление для этого — не читать входные данные по одному символу за раз, как только я вижу нулевой символ (который равен 0 ASCII), я останавливаюсь. Предложение try внутри метода recvStr () можно заменить следующим:

    try {
int a = -1;
while(true){
a = br.read();
if(a == 0)
break;
message = message + (char)a;
}

}
-1

Другие решения

Других решений пока нет …