Я пытаюсь создать соединение сервер-клиент с использованием сокетов.Сервер - это просто Эхо-сервер.Я хочу отправить туда разные типы данных.Я начал с изображений.Чего я хочу добиться:
- Анализировать изображение, хранящееся в папке ресурсов, в соответствующий тип данных
- Отправить его на Echo Server
- Получить данные обратно на мобильный(клиент) site
- Отображение изображения, отправленного таким образом (чтобы убедиться, что данные были отправлены правильно)
Я реализовал и Клиент, и Сервер.Клиент во Флаттере, Сервер в Ктор.Реализация сервера была скопирована из учебника: https://ktor.io/servers/raw-sockets.html. Я вижу, что мой сервер получает изображение и отправляет его обратно правильно, но я не могу его показать.
Код сервера:
fun main() {
runBlocking {
val server = aSocket(ActorSelectorManager(Dispatchers.IO)).tcp().bind(InetSocketAddress("localhost", 8080))
println("Started echo telnet server at ${server.localAddress}")
while (true) {
val socket = server.accept()
launch {
println("Socket accepted: ${socket.remoteAddress}")
val input = socket.openReadChannel()
val output = socket.openWriteChannel(autoFlush = true)
try {
while (true) {
val line = input.readUTF8Line()
line?.let {
println("Client sent: $line")
output.writeStringUtf8(it)
}
}
} catch (e: Throwable) {
println("Closing socket")
e.printStackTrace()
socket.close()
}
}
}
}
}
и клиент:
class MyHomePage extends StatefulWidget {
final String title;
MyHomePage({Key key, @required this.title}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Socket _socket;
List<int> _connectionTimes = [];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: const Text('Connect to socket'),
color: Theme.of(context).accentColor,
elevation: 4.0,
onPressed: () {
closeSocket();
_connectToSocket().then((createdSocket) {
setState(() {
_socket = createdSocket;
});
});
},
),
RaisedButton(
child: const Text('Send to socket'),
color: Theme.of(context).accentColor,
elevation: 4.0,
onPressed: () {
_sendMessage();
},
),
StreamBuilder(
stream: _socket,
builder: (context, snapshot) {
if(snapshot.hasData) {
final bytes = base64Decode(utf8.decode(snapshot.data));
return Image.memory(bytes);
} else {
return Text("no image");
}
},
),
],
)),
);
}
Future<Socket> _connectToSocket() async {
final stopwatch = Stopwatch()..start();
Socket sock = await Socket.connect('10.0.2.2', 8080);
print("Connection time was ${stopwatch.elapsedMilliseconds}");
return sock;
}
void _sendMessage() async{
final imageBytes = await rootBundle.load('assets/images/dog.jpeg');
final bytesAsString = base64Encode(imageBytes.buffer.asUint8List(imageBytes.offsetInBytes, imageBytes.lengthInBytes));
print(bytesAsString);
_socket.write(bytesAsString+"\n");
}
void closeSocket() {
if (_socket != null) {
_socket.close();
}
}
@override
void dispose() {
_socket.close();
super.dispose();
}
}
Я получаю ошибку:
E/flutter ( 8235): [ERROR:flutter/lib/ui/painting/codec.cc(97)] Failed decoding image. Data is either invalid, or it is encoded using an unsupported format.
I/flutter ( 8235): ══╡ EXCEPTION CAUGHT BY IMAGE RESOURCE SERVICE ╞════════════════════════════════════════════════════
I/flutter ( 8235): The following _Exception was thrown resolving an image codec:
I/flutter ( 8235): Exception: operation failed
I/flutter ( 8235): ════════════════════════════════════════════════════════════════════════════════════════════════════
И, кроме того, у меня есть еще несколько вопросов:
Есть ли лучший способ разобрать изображение из ресурсов во Flutter?
Есть ли способ отправить эти данные без добавления \n
в концеданные изображения?
Возможно ли, что изображение будет слишком большим, и я не смогу отправить его за один запрос?Если да, что я должен изменить в коде, чтобы он работал?Разделите его на несколько вызовов и используйте буфер на клиенте и на сервере?
Что я должен изменить в коде сервера, чтобы я мог запустить его один раз, а также подключаться и отключаться с помощью одного клиентамногократно?(Это раздражает, что при каждом изменении, которое я вносю в код Flutter, мне приходится перезапускать сервер, чтобы он работал правильно?
Я открыт для изменения реализации сервера на другой каркас / языкЯ хочу использовать Flutter, но это не обязательно должен быть Ktor на сайте сервера. Просто хотел проверить это в действии.