客户端和服务器侦听请求

时间:2013-12-05 21:47:22

标签: c# sockets asynchronous

我想知道我的思维方式是否有益。 这是情况:

  • 服务器正在接受连接的异步。接受后,在接受的套接字上接收异步。
  • 客户端将异步连接到服务器,然后侦听请求异步。

我想要做的是从客户端和服务器发送请求。另一方应该接受它。

服务器代码:

    public ServerHandler()
    {
        _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        _serverSocket.Bind(_ipLocal);
        _serverSocket.Listen(4);
        _serverSocket.BeginAccept(AcceptCallback, null);
    }

    private void AcceptCallback(IAsyncResult ar)
    {
        Socket socket = (Socket)ar.AsyncState;
        _clients.Add(socket);

        socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, RecieveCallback, socket);
        _serverSocket.BeginAccept(AcceptCallback, null);
    }

    private void RecieveCallback(IAsyncResult ar)
    {
        var socket = (Socket) ar.AsyncState;
        var recieved = socket.EndReceive(ar);
        var dataBuff = new byte[recieved];

        Array.Copy(_buffer, dataBuff, recieved);

        OnMessageRecieved(dataBuff);

        socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, RecieveCallback, socket);
    }

    private void Send(byte[] data, Socket socket)
    {
        socket.BeginSend(data, 0, data.Length, SocketFlags.None,
                SendCallback, socket);
    }

    private void SendCallback(IAsyncResult ar)
    {
        var socket = (Socket)ar.AsyncState;
        socket.EndSend(ar);
    }

    private void SendToAll(byte[] data)
    {
        foreach (var clientSocket in _clients)
        {
            Send(data, clientSocket);
            Debug.WriteLine("sent to: " + clientSocket.LocalEndPoint);
        }
    }

客户代码:

    public ClientHandler()
    {
        _ipLocal = new IPEndPoint(IPAddress.Parse(ServerIp), Port);
    }

    public void ConnectLoop()
    {
        int attempts = 0;
        while (!_clientSocket.Connected)
        {
            try
            {
                attempts++;
                _clientSocket.BeginConnect(IPAddress.Parse(ServerIp), Port, ConnectCallback, null);
                _clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, RecieveCallback,
                                           _clientSocket);
            }
            catch (Exception)
            {
                Debug.WriteLine("Connection attempts: " + attempts);
            }
        }

        Debug.WriteLine("Connected");
    }

    private void ConnectCallback(IAsyncResult ar)
    {
        _clientSocket.EndConnect(ar);
    }

    private void RecieveCallback(IAsyncResult ar)
    {
        var socket = (Socket) ar.AsyncState;
        int recieved = _clientSocket.EndReceive(ar);
        var dataBuff = new byte[recieved];

        Array.Copy(_buffer, dataBuff, recieved);

        OnMessageRecieved(dataBuff);

        _clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, RecieveCallback, _clientSocket);
    }

    private void Send(byte[] data, Socket socket)
    {
        socket.BeginSend(data, 0, data.Length, SocketFlags.None,
                SendCallback, socket);
    }

    private void SendCallback(IAsyncResult ar)
    {
        var socket = (Socket)ar.AsyncState;
        socket.EndSend(ar);
    }

请问这项工作吗?

EDIT1:哦,我想通过1个套接字来做。客户端/服务器在同一个套接字上发送和接收。但是可以有多个客户端套接字,但对于客户端 - 服务器对只有1个。

1 个答案:

答案 0 :(得分:1)

如果没有测试,您的代码看起来不错,但是,您需要提供额外的代码来确定您是否收到了完整的消息。

执行阅读时,您可能会遇到以下情况之一:

  • 一些消息,但不是全部
  • 完全是一条消息
  • 所有消息加上一些/所有其他消息
  • 套接字错误(断开连接等)。

有一些普遍接受的方法可以确定整个消息是什么:

  • 分隔您的消息,以便您的接收代码需要查找分隔符
  • 具有某种嵌入的固定邮件大小,以指示是否有更多邮件
  • 可变消息大小但具有固定的“大小”部分,首先发送,即前4个字节将指示消息的大小。所以你知道你总是需要4个字节来确定消息的长度;然后你就知道要为下一条消息处理多少。

此SO帖子Chat service application还有一些关于处理邮件的链接。