Как отправить массив байтов через TCP-соединение (Java-программирование) - PullRequest
25 голосов
/ 21 мая 2010

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

byte[] myByteArray

(Я новичок в программировании на Java и, похоже, не могу найти пример того, как это сделать, который показывает оба конца соединения (отправитель и получатель). Если вы знаете существующий пример, возможно, вы могли бы опубликовать ссылку. (Не нужно изобретать велосипед.) PS Это НЕ домашнее задание!: -)

Ответы [ 9 ]

56 голосов
/ 21 мая 2010

Классы InputStream и OutputStream в Java изначально обрабатывают байтовые массивы. Единственное, что вы можете добавить, - это длину в начале сообщения, чтобы получатель знал, сколько байтов ожидать. Обычно я хотел бы предложить метод, который позволяет контролировать, какие байты в байтовом массиве отправлять, очень похоже на стандартный API.

Примерно так:

private Socket socket;

public void sendBytes(byte[] myByteArray) throws IOException {
    sendBytes(myByteArray, 0, myByteArray.length);
}

public void sendBytes(byte[] myByteArray, int start, int len) throws IOException {
    if (len < 0)
        throw new IllegalArgumentException("Negative length not allowed");
    if (start < 0 || start >= myByteArray.length)
        throw new IndexOutOfBoundsException("Out of bounds: " + start);
    // Other checks if needed.

    // May be better to save the streams in the support class;
    // just like the socket variable.
    OutputStream out = socket.getOutputStream(); 
    DataOutputStream dos = new DataOutputStream(out);

    dos.writeInt(len);
    if (len > 0) {
        dos.write(myByteArray, start, len);
    }
}

РЕДАКТИРОВАТЬ : Чтобы добавить получающую сторону:

public byte[] readBytes() throws IOException {
    // Again, probably better to store these objects references in the support class
    InputStream in = socket.getInputStream();
    DataInputStream dis = new DataInputStream(in);

    int len = dis.readInt();
    byte[] data = new byte[len];
    if (len > 0) {
        dis.readFully(data);
    }
    return data;
}
4 голосов
/ 21 мая 2010

Просто начните с этого примера из Really Big Index . Обратите внимание, что он предназначен для передачи и получения символов, а не байтов. Это не так уж и сложно - вы можете просто работать с необработанными InputStream и OutputStream объектами, которые предоставляет класс Socket См. API для получения дополнительной информации о различных типах читателей, писателей и потоков. Методы, которые вас заинтересуют: OutputStream.write(byte[]) и InputStream.read(byte[]).

2 голосов
/ 21 мая 2010

Учебное пособие по сокетам Oracle может показаться подходящей точкой запуска.

Обратите внимание, что дополнительные проблемы превращают символы в байты. Если вы хотите работать на уровне байтов, просто снимите это.

1 голос
/ 09 марта 2015

Я бы попросил вас использовать ObjectOutputStream и ObjectInputStream. Они отправляют все как объект и получают как то же самое.

ObjectOutputStream os = new ObjectOutputStream(socket.getOutputStream());
os.flush();
ObjectInputStream is = new ObjectInputStream(socket.getInputStream());
os.writeObject(byte_array_that_you_want_to_send);
byte[] temp = (byte[]) is.readObject();

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

1 голос
/ 21 мая 2010

Вам необходимо использовать метод write для java.io.OutputStream и метод read для java.io.InputStream, оба из которых вы можете получить из Socket, который вы открыли.

1 голос
/ 21 мая 2010

Этот учебник Sun Sockets должен дать вам хорошую отправную точку

0 голосов
/ 24 ноября 2016

Ниже приведен пример потоковой передачи 100-байтовых кадров файла wav.

private Socket socket;

public void streamWav(byte[] myByteArray, int start, int len) throws IOException {

    Path path = Paths.get("path/to/file.wav");

    byte[] data = Files.readAllBytes(path);

    OutputStream out = socket.getOutputStream();
    DataOutputStream os = new DataOutputStream(out);

    os.writeInt(len);
    if (len > 0) {
        os.write(data, start, len);
    }
}

public void readWav() throws IOException {

    InputStream in = socket.getInputStream();

    int frameLength = 100; // use useful number of bytes

    int input;
    boolean active = true;

    while(active) {
        byte[] frame = new byte[frameLength];
        for(int i=0; i<frameLength; i++) {

            input = in.read();

            if(input < 0) {
                active = false;
                break;
            } else frame[i] = (byte) input;
        }

        // playWavPiece(frame);
        // streamed frame byte array is full
        // use it here ;-)
    }
}
0 голосов
/ 17 октября 2016
import java.io.*;
import java.net.*;

public class ByteSocketClient 
{
    public static void main(String[] args) throws UnknownHostException, IOException 
    {
        Socket s=new Socket("",6000);

        DataOutputStream dout=new DataOutputStream(new BufferedOutputStream(s.getOutputStream()));

        byte[] a = {(byte)0xC0,(byte)0xA8,(byte)0x01,(byte)0x02,(byte)0x53,(byte)0x4D,(byte)0x41,(byte)0x52,(byte)0x54};
        dout.write(a);
        dout.close();
        s.close();
    }

}
0 голосов
/ 07 декабря 2012

Я предполагаю, что вопрос сформулирован неправильно. Я нашел это при поиске ответа на вопрос, почему мое использование InputStream и OutputStream, по-видимому, устанавливало весь массив в 0 при обнаружении байта значения 0. Предполагают ли они, что байты содержат действительный ASCII, а не двоичный. Поскольку вопрос не подходит и не задает его, и никто другой, кажется, не воспринял это как возможность, я думаю, мне придется выполнить свой квест в другом месте.

Я пытался написать класс TransparentSocket, который может создать экземпляр TCP (Socket / ServerSocket) или UDP (DatagramSocket) для прозрачного использования DatagramPacket. Он работает для UDP, но не (пока) для TCP.

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

новый DataOutputStream (socket.getOutputStream ()). WriteInt (5);

^ Так много для этой идеи. Он записывает данные «переносимым» способом, то есть, вероятно, в ASCII, что совсем не помогает, особенно при эмуляции программного обеспечения, которое я не контролирую!

...