客户端只在发送消息时监听服务器

Client only listens to server when sends a message

我正在实现套接字。 两个客户端连接到服务器没有问题,当 client1 向服务器发送消息时,服务器将其发布给所有其他客户端(在本例中为 client2)。但是 client2 除非发送消息,否则不会收到消息。客户端的监听器似乎不起作用。很明显,我想让client2立即得到client1的消息。

这是我的服务器代码:

import 'dart:io';
import 'dart:typed_data';

void main() async {
  // bind the socket server to an address and port
  MySocket mySocket = MySocket();
  await mySocket.init();
}

class MySocket {
  ServerSocket? server;
  List<Socket> clients = [];

  //initialize the socket
  init() async {
    server = await ServerSocket.bind("192.168.0.112", 4000);
    // listen for client connections to the server
    server!.listen((client) {
      handleConnection(client);
      addClient(client);
    });
  }

  void handleConnection(Socket client) async {
    print('Connection from'
        ' ${client.remoteAddress.address}:${client.remotePort}');

    // listen for events from the client
    client.listen(
      // handle data from the client
      (Uint8List data) async {
        await Future.delayed(Duration(seconds: 1));
        final message = String.fromCharCodes(data);
        print(message);
        publish(message, client);
      },

      // handle errors
      onError: (error) {
        print(error);
        client.close();
      },

      // handle the client closing the connection
      onDone: () {
        print('Client left');
        client.close();
      },
    );
  }

  void addClient(Socket client) {
    //if client doesn't already exist add it to the list of clients
    if (!clients.any((element) =>
        '${client.remoteAddress.address}:${client.remotePort}' ==
        '${element.remoteAddress.address}:${element.remotePort}')) {
      clients.add(client);
    }
  }

  void publish(String message, Socket client) {
    //write the message to every client except the author of it
    clients.forEach((element) async {
      if ('${client.remoteAddress.address}:${client.remotePort}' !=
          '${element.remoteAddress.address}:${element.remotePort}') {
        element.write(message);
      }
    });
  }
}

这是我的客户端代码:

import 'dart:io';
import 'dart:typed_data';

void main() async {
  //gets the username
  String name = '';
  while (name.isEmpty) {
    print('Enter your name: ');
    name = stdin.readLineSync() ?? '';
  }

  // connect to the socket server
  final socket = await Socket.connect("192.168.0.112", 4000);
  print('Connected to: ${socket.remoteAddress.address}:${socket.remotePort}');


  // listen for responses from the server
  socket.listen(
    // handle data from the server
    (Uint8List data) {
      final serverResponse = String.fromCharCodes(data);
      print('$serverResponse');
    },

    // handle errors
    onError: (error) {
      print(error);
      socket.destroy();
    },

    // handle server ending connection
    onDone: () {
      print('Left server.');
      socket.destroy();
    },
  );


  // sending messages to the server
  String message = "";
  while (message != "exit") {
    message = stdin.readLineSync() ?? '';
    await sendMessage(socket, name, message);
  }
  socket.close();
}


Future<void> sendMessage(Socket socket, String name, String message) async {
  socket.write('$name: $message');
  await Future.delayed(Duration(seconds: 2));
}

提前致谢。

问题是因为您的客户端中的 stdin.readLineSync() 阻塞了当前线程。您可以通过生成一个隔离来处理该部分代码来解决这个问题,这样它就不会阻止 socket.listen 打印出服务器的响应。

查看下面更新的客户端代码:

import 'dart:io';
import 'dart:isolate';
import 'dart:typed_data';

void main() async {
  //gets the username
  String name = '';
  while (name.isEmpty) {
    print('Enter your name: ');
    name = stdin.readLineSync() ?? '';
  }

  // connect to the socket server
  final socket = await Socket.connect("192.168.0.112", 4000);
  print('Connected to: ${socket.remoteAddress.address}:${socket.remotePort}');

  // listen for responses from the server
  socket.listen(
    // handle data from the server
    (Uint8List data) {
      final serverResponse = String.fromCharCodes(data);
      print('$serverResponse');
    },

    // handle errors
    onError: (dynamic error) {
      print(error);
      socket.destroy();
    },

    // handle server ending connection
    onDone: () {
      print('Left server.');
      socket.destroy();
    },
  );

  final receive = ReceivePort();
  final isolate = await Isolate.spawn(readMessages, receive.sendPort);
  await for (final message in receive) {
    if (message == 'exit') break;
    await sendMessage(socket, name, message as String);
  }

  socket.close();
}

void readMessages(SendPort port) {
  String message = '';
  while (message != 'exit') {
    message = stdin.readLineSync() ?? '';
    port.send(message);
  }
  Isolate.exit(port);
}

Future<void> sendMessage(Socket socket, String name, String message) async {
  socket.write('$name: $message');
  await Future<void>.delayed(Duration(seconds: 2));
}