C# - Asynchron Socket获取错误的byte []长度

时间:2015-10-15 12:23:07

标签: c# sockets asynchronous server client

你好社区, 我遇到了一个大问题。 我想用C#创建一个客户端 - 服务器应用程序。

但是如果我将数据作为byte []发送给我的客户端,他会在服务器发送时获得更多字节。

如果我使用字符串x = Encoding.UTF8.GetString(bytesFromServer); 此字符串中的信息少于我的服务器上的信息。

我真的很困惑。 我希望你能帮助我。

服务器代码:

public class Server
{
    private static object serverLock = new object();

    private static int port = 5177;
    private static Socket serverSocket;

    private class ConnectionInfo
    {
        public string deviceName;
        public Socket Socket;
        public byte[] Buffer;
    }

    private static List<ConnectionInfo> connections = new List<ConnectionInfo>();

    public static void Start()
    {
        try
        {
            createAndStartSocket();
            for (int i = 0; i < 10; i++)
            {
                serverSocket.BeginAccept(new AsyncCallback(acceptCallback), serverSocket);
            }
        }
        catch (Exception e)
        {
            Debug.WriteLine("Error: ");
            Debug.WriteLine(e.ToString());
        }
    }

    public static void Stop()
    {
        try
        {
            serverSocket.Close();
        }
        catch
        {
            Debug.WriteLine("Error while Closing Socket!");
        }
    }

    private static void createAndStartSocket()
    {
        IPEndPoint myEndpoint = new IPEndPoint(IPAddress.Any, port);

        serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        serverSocket.Blocking = false;

        serverSocket.Bind(myEndpoint);
        serverSocket.Listen((int)SocketOptionName.MaxConnections); ;
    }

    private static void acceptCallback(IAsyncResult result)
    {
        ConnectionInfo connection = new ConnectionInfo();
        try
        {
            Socket s = (Socket)result.AsyncState;
            connection.Socket = s.EndAccept(result);
            connection.Socket.Blocking = false;
            connection.Buffer = new byte[1024];
            lock (connections)
            {
                connections.Add(connection);
            }

            Debug.WriteLine("New connection from " + s);

            // Start Receive
            connection.Socket.BeginReceive(connection.Buffer, 0, connection.Buffer.Length, SocketFlags.Partial, new AsyncCallback(receiveCallback), connection);

            serverSocket.BeginAccept(new AsyncCallback(acceptCallback), result.AsyncState);
        }
        catch (Exception e)
        {
            closeConnection(connection);
            Debug.WriteLine("Exception: ");
            Debug.WriteLine(e.ToString());
        }
    }

    private static void closeConnection(ConnectionInfo connection)
    {
        connection.Socket.Close();
        lock (connections)
        {
            connections.Remove(connection);
        }

    }

    private static void receiveCallback(IAsyncResult result)
    {
        ConnectionInfo connection = (ConnectionInfo)result.AsyncState;
        try
        {
            int bytesRead = connection.Socket.EndReceive(result);
            if (0 != bytesRead)
            {
                string command = String.Empty;
                command = UTF8Encoding.UTF8.GetString(connection.Buffer);

                byte[] answer = DataController.GetData(command);

                lock (connections)
                {
                    foreach (ConnectionInfo conn in connections)
                    {
                        if (connection == conn)
                        {
                            conn.Socket.Send(answer, answer.Length,
                                SocketFlags.Partial);
                        }
                    }
                }
                connection.Socket.BeginReceive(connection.Buffer, 0,
                    connection.Buffer.Length, SocketFlags.Partial,
                    new AsyncCallback(receiveCallback), connection);
            }
        }
        catch
        {
            closeConnection(connection);
        }
    }
}

和客户:

public class SocketInfo
{
    public byte[] Buffer = new byte[1024];
    public Socket Socket = null;
    public List<byte> byteList = new List<byte>();
}

public class Connection
{
    private string _address;
    private int _port;
    private IPEndPoint _clientEndpoint;
    private List<SocketInfo> socketList = new List<SocketInfo>();


    public bool Start(string address, int port)
    {
        _address = address;
        _port = port;

        IPAddress add = IPAddress.Parse(_address);
        _clientEndpoint = new IPEndPoint(add, _port);
        _address = _clientEndpoint.Serialize().ToString();

        Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        SocketInfo info = new SocketInfo();
        info.Socket = clientSocket;

        lock (socketList)
        {
            socketList.Add(info);
        }

        Debug.Write("Connecting... ");

        try
        {
            info.Socket.Connect(_clientEndpoint);
            Debug.WriteLine("Done.");

            info.Socket.BeginReceive(info.Buffer, 0, info.Buffer.Length, SocketFlags.None, new AsyncCallback(receiveCallback), info);
            return true;
        }
        catch (Exception e)
        {
            lock (socketList)
            {
                socketList.Remove(info);
            }
            Debug.WriteLine("Fail.");
            Debug.WriteLine(e);
            return false;
        }
    }

    public bool SendRequestToServer(string[] command)
    {
        try
        {
            switch (command[0])
            {
                case "service":
                    Thread th = new Thread(new ThreadStart(ServicesThread));
                    th.Start();
                    break;

                default:
                    break;
            }
            return true;
        }
        catch
        {
            return false;
        }
    }

    private void ServicesThread()
    {
        try
        {
            byte[] request = Encoding.UTF8.GetBytes("runningservices");

            lock (socketList)
            {
                foreach (SocketInfo si in socketList)
                {
                    si.Socket.Send(request, request.Length,
                        SocketFlags.None);
                    Debug.WriteLine("serviceRequest sendet!");

                    si.Socket.BeginReceive(si.Buffer, 0,
                        si.Buffer.Length, SocketFlags.None,
                        new AsyncCallback(receiveCallback), si);
                }
            }

        }
        catch (Exception e)
        {
            Console.WriteLine("Unable to send data. Connection lost.");
        }

        Thread.Sleep(10);
        Debug.WriteLine("Services thread stopped.");
    }

    private void receiveCallback(IAsyncResult result)
    {
        SocketInfo info = (SocketInfo)result.AsyncState;
        try
        {
            int bytesToRead = info.Socket.EndReceive(result);
            if (bytesToRead > 0)
            {
                info.byteList.AddRange(info.Buffer);
                //  Get the rest of the data.
                if (bytesToRead == info.Buffer.Length)
                {
                    info.Socket.BeginReceive(info.Buffer, 0, info.Buffer.Length, 0,
                        new AsyncCallback(receiveCallback), info);
                }
                else
                {
                    if (info.byteList.Count > 0)
                    {
                        byte[] completeMessage = info.byteList.ToArray();
                        string incommingResult = Encoding.UTF8.GetString(completeMessage);
                        info.byteList.Clear();

                        //Following Code

                        info.Socket.BeginReceive(info.Buffer, 0, info.Buffer.Length, 0,
                        new AsyncCallback(receiveCallback), info);
                    }
                }
            }
            else
            {
                if (info.byteList.Count > 0)
                {
                    byte[] completeMessage = info.byteList.ToArray();                        
                    string incommingResult = Encoding.UTF8.GetString(completeMessage);
                    info.byteList.Clear();

                    //Following Code
                }
            }
        }
        catch (Exception e)
        {
            lock (socketList)
            {
                socketList.Remove(info);
            }
            Debug.WriteLine("Client Disconnected.");
            Debug.WriteLine(e);
        }
    }
}

在我的情况下,服务器说“answer.Length”= 9895 客户说“completeMessage.Length”= 9945。

我希望你能帮助我。 谢谢!

1 个答案:

答案 0 :(得分:0)

您总是在这里添加缓冲区的全部内容:

info.byteList.AddRange(info.Buffer);

只需添加使用的缓冲区部分:

info.byteList.AddRange(info.Buffer.Take(bytesToRead));