简体   繁体   中英

Clients and Server Listening for requests

I would like to know if my way of thinking is any good. Here is sitution:

  • Server is accepting async for connections. After accept is recieveing async on accepted sockets.
  • Clients are connecting async to server, then listening for request async.

What I want to do is to send requests from both client and server. Other side should recieve it.

Server code:

    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);
        }
    }

Client code:

    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);
    }

Will sth like this work?

EDIT1: Oh, and I want to do it through 1 socket. Client/server sending and recieveing on same socket. But there can be multiple clients sockets , but only 1 for pair client-server.

Without testing, your code looks alright however, you'll need to provide extra code to determine if you've got a whole message or not.

When you do a read, you may get one of the following scenarios:

  • Some of a message, but not all
  • exactly all of a message
  • all of a message plus some/all of another message
  • a socket error (disconnected etc).

There are a few generally accepted methods of determining what a whole message is:

  • delimiting your message so your receival code needs to look for the delimiters
  • A fixed message size with some sort of embedding to indicate if there are more messages
  • a variable message size but with a fixed "size" part which is transmitted first Ie say the first 4 bytes will indicate the size of the message. So you know you always need 4 bytes first to determine the length of the message; and then you know how much to process for the next message.

This SO post Chat service application has some more and links on processing messages.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM