Я пытаюсь повторно использовать один и тот же сокет для отправки и получения строк (и / или байтов) между клиентом 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)
Я выяснил, что является причиной проблемы, однако я не знаю, почему это вызывает проблему. Проблема заключается в том, что я использую массивы 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;
}
}
Других решений пока нет …