Вы можете получить дескриптор файла (который Apple называет «Native Handle»), и с его помощью использовать типичные сетевые команды POSIX для получения адреса:
Получить дескриптор файла из потока:
CFDataRef handleData = (CFDataRef)CFReadStreamCopyProperty((__bridge CFReadStreamRef) inputStream, kCFStreamPropertySocketNativeHandle);
long length = CFDataGetLength(handleData);
uint8_t * buffer = malloc(length);
CFDataGetBytes(handleData, CFRangeMake(0, length), buffer);
int sock_fd = (int)*buffer;
Получите удаленный адрес для этого дескриптора файла:
struct sockaddr addr;
socklen_t addr_len = sizeof(addr);
getpeername(sock_fd, &addr, &addr_len);
NSString * remoteAddr;
if (addr.sa_family == AF_INET) {
char addressString[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &((struct sockaddr_in *)&addr)->sin_addr, addressString, INET_ADDRSTRLEN);
remoteAddr = [[NSString alloc] initWithUTF8String:addressString];
} else if (addr.sa_family == AF_INET6) {
char addressString[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr)->sin6_addr, addressString, INET6_ADDRSTRLEN);
remoteAddr = [[NSString alloc] initWithUTF8String:addressString];
}
free(buffer);
// Now you have remoteAddr which will be a
// string representation of a IPv4 or IPv6 address!
NSLog(@"Remote Address: %@", remoteAddr);
Если у Вас действительно есть файл (а не что-то тяжелее для поиска в, например, сетевой поток) затем, я предлагаю что-то вроде этого:
Вы могли просто звонить mark()
в начале FileInputStream и затем reset()
и skip()
добираться до правильного места, если Вы не хотите вновь открыть файл. (Я искал InputStream.seek()
но я не вижу один - я не могу помнить желать это прежде в Java, но разве это действительно не имеет того? Ick.)
Вы могли использовать RandomAccessFile
. Использовать readLine()
прочитать простой текст в запуске (отмечают ограничения этого, как описано в API), и затем readByte()
или readFully()
считывать последующие двоичные данные.
Используя базовое
FileInputStream
считать возвраты пустые массивы байтов.
Поэтому Вы перенесли поток в a BufferedReader
, который, вероятно, использовал все байты от потока при заполнении его буфера.
Необходимо использовать InputStream. Читатели для символьных данных. Изучите обертывание Вашего входного потока с DataInputStream, как:
stream=new DataInputStream(new BufferedInputStream(new FileInputStream(...)));
Поток ввода данных даст Вам много полезных методов для чтения различных типов данных, и конечно, основные методы InputStream для чтения байтов.
(Это на самом деле точно, что сервер HTTP должен сделать для чтения запроса с содержанием.)
readUTF не читает строку, он читает строку, которая была записана в (измененном) формате UTF8 - относятся к JavaDoc.
Корректный путь состоит в том, чтобы использовать InputStream некоторой формы, вероятно, FileInputStream, если это не становится барьером производительности.
Что делает Вы означаете "Используя базовый FileInputStream читать возвраты пустые массивы байтов".? Это кажется очень маловероятным и, вероятно, где Ваша ошибка. Можно ли показать нам пример кода, который Вы попробовали?
Можно прочитать текст с BufferedReader. Когда Вы знаете, где двоичный файл запускается, можно закрыть файл и открыть его с RandomAccessFile и считать двоичный файл из любой точки в файле. Или можно считать файл, столь же двоичный, и преобразовать для отправки текстовых сообщений разделам, которые Вы определяете как текст. {Используя новую Строку (байты, кодируя)}
Я рекомендую использовать DataInputStream. У Вас есть следующие опции:
Увы, DataInputStream
устарел и не поддерживает UTF. Но это должно помочь (он считывает строку из двоичного потока без предварительного просмотра).
public static String lineFrom(InputStream in) throws IOException {
byte[] buf = new byte[128];
int pos = 0;
for (;;) {
int ch = in.read();
if (ch == '\n' || ch < 0) break;
buf[pos++] = (byte) ch;
if (pos == buf.length) buf = Arrays.copyOf(buf, pos + 128);
}
return new String(Arrays.copyOf(buf, pos), "UTF-8");
}