Чат с возможностью отправки файла - PullRequest
0 голосов
/ 07 января 2019

Я хотел бы создать простой TCP-чат с возможностью отправки файлов.
Отправка сообщений другим клиентам работает, но отправка файлов не работает. Мой чат отправляет только несколько байтов файла.

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

Сервер написан на C, а Клиент написан на Java (у меня были такие рекомендации).

Сервер:

    for (i = 0; i < max_clients; i++) {
        sd = client_socket[i]; 

        memset(buffer, 0, 10000);
        if (FD_ISSET( sd , &readfds)) {
            if ((valread = read( sd , buffer, 1024)) == 0) {
                getpeername(sd, (struct sockaddr*)&address, (socklen_t*)&addrlen); 
                printf("Host disconnected , ip %s , port %d \n" , 
                    inet_ntoa(address.sin_addr) , ntohs(address.sin_port)); 



                close( sd ); 
                client_socket[i] = 0; 
            } 
            else {
                // When message "start" arrived download the file and send it back to other clients
                if (strcmp(buffer, "start") == 0) {
                    uint8_t buff[10000];
                    // Read chunks of file
                    while (read( sd , buff, sizeof(buff)) > 0) {

                        // Sending chunks of file to other clients
                        for(j=0; j<max_clients; j++) {
                            int outSock = client_socket[j];
                            if(outSock != master_socket && outSock != sd) {
                                send(outSock , buff , sizeof(buff) , 0 ); 
                            }
                    }

                    }
                } else {

                    buffer[valread] = '\0'; 
                    for(j=0; j<max_clients; j++) {
                        int outSock = client_socket[j];
                        if(outSock != master_socket && outSock != sd) {
                            send(outSock , buffer , strlen(buffer) , 0 ); 
                        }
                    }

                }

            } 
        } 
    }

Клиент:

@FXML
void sendFile(ActionEvent event) {
    FileChooser fileChooser = new FileChooser();
    File file = fileChooser.showOpenDialog(null);

    // Send "start" message to let server know that I'm going to send a file
    out.println("start");
    out.flush();

    try {

        FileInputStream fis = new FileInputStream(file);
        BufferedInputStream bis = new BufferedInputStream(fis);

        //Get socket's output stream
        OutputStream os = clientSocket.getOutputStream();

        //Read File Contents into contents array
        byte[] contents;
        long fileLength = file.length();
        long current = 0;

        while(current!=fileLength){
            int size = 10000;
            if(fileLength - current >= size)
                current += size;
            else{
                size = (int)(fileLength - current);
                current = fileLength;
            }
            contents = new byte[size];
            bis.read(contents, 0, size);
            os.write(contents);
            System.out.print("Sending file ... "+(current*100)/fileLength+"% complete!");
        }

        os.flush();
        System.out.println("File sent successfully!");

    } catch(Exception e) {

    }
}

public ChatWindowController() {

    try {
        clientSocket = new Socket("127.0.0.1", 54000);
        outToServer = new DataOutputStream(clientSocket.getOutputStream());
        inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        out = new PrintWriter(clientSocket.getOutputStream(), true);

        thread = new Thread() {
            @Override
            public void run() {
                try {

                    while(isRunning) {
                        if (ta_display != null) {
                            String message = inFromServer.readLine();
                            if (!isDownloadingFile) {
                                System.out.println(message);
                                ta_display.appendText(message + '\n');

                                if (message.equals("start")) {
                                    isDownloadingFile = true;
                                }
                            } else {

                                byte[] contents = new byte[10000];

                                //Initialize the FileOutputStream to the output file's full path.
                                FileOutputStream fos = new FileOutputStream("/example/test.png");
                                BufferedOutputStream bos = new BufferedOutputStream(fos);
                                InputStream is = clientSocket.getInputStream();

                                //No of bytes read in one read() call
                                int bytesRead = 0;

                                while((bytesRead=is.read(contents))!=-1)
                                    bos.write(contents, 0, bytesRead);

                                bos.flush();

                                System.out.println("File saved successfully!");

                            }
                        }

                    }

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

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

Когда я нажимаю кнопку, вызывается метод sendFile, затем я выбираю файл и хочу отправить этот файл, а другие клиенты скачивают его.

Ответы [ 2 ]

0 голосов
/ 08 января 2019

Я написал похожий пример для чата на https://github.com/foreverpersist/socket/blob/master/chatroom.c.

Передача файлов осуществляется через P2P

  1. Сервер сообщает <IP:PORT> об отправителе и получателе друг другу.
  2. Отправитель и получатель соединяются друг с другом напрямую.
  3. Отправитель отправляет файл получателю.
  4. Отправитель и получатель закрывают соединение.

Как и в вашем проекте, при передаче файлов с путем Sender -> Server -> Receiver содержимое больших файлов может быть неполным, если вы не поступите осторожно. Итак, я просто передаю файлы с путем Sender -> Receiver.

0 голосов
/ 07 января 2019

Хорошо, на сервере произошла ошибка при получении файла:

//client sends 10000 bytes of data in chunks of unknown size

//receive one chunk of unknown size
while (read( sd , buff, sizeof(buff)) > 0) {
    for(j=0; j<max_clients; j++) {
        int outSock = client_socket[j];
        if(outSock != master_socket && outSock != sd) {
            // Send 10000 bytes aka the received chunk and whatever else is in the buffer to all clients
            send(outSock , buff , sizeof(buff) , 0 ); 
        }
    }

Вам необходимо либо сначала получить все данные, а затем отправить их клиентам, либо отправить только размер фрагмента в несколько байтов, как в модуле записи файлов в клиенте или следующим образом:

int chunk = 0;
while ((chunk = read( sd , buff, sizeof(buff))) > 0) {
    ...
    send(outSock , buff , chunk , 0);

Также я не уверен, что код записи файла клиента работает, вы должны убедиться, что в файл случайно не записаны следующие сообщения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...