网络套接字-只是第一个消息总是完成

本文关键字:消息 第一个 套接字 -只 网络 | 更新日期: 2023-09-27 17:51:04

我在客户端套接字(同步)/服务器套接字(异步)环境中遇到了以下问题。如果我从客户端向服务器发送多条消息,第一条消息将毫无问题地完成,并且将被客户端毫无问题地接收。当我发送第二条消息时,只有几个字节通过。这似乎不是客户端的问题,因为看起来客户端一直在发送完整的消息。疯狂的事情是,如果我在客户端完全停止项目并重新开始,第一个消息再次完成,如果服务器组件一直运行。

我想做的是…基本上,我想通过网络传输不同的对象,大多数xml结构化,并在客户机上接收它。因此,我执行序列化/反序列化。以下代码的基础是扩展的msdn示例。

//客户:

class ProgramClient
{
    static void Main(string[] args)
    {
        string rootNode = "config";
        StreamReader configStream = new StreamReader(config);
        XmlDocument xml = new XmlDocument();
        xml.Load(configStream);
        SynchronousSocketClient socket = new SynchronousSocketClient("192.168.0.1", 40001, "c:''log", xml);
        socket.StartClient();
        socket.Dispose();
        socket = new SynchronousSocketClient("192.168.0.1", 40001, "c:''log", xml);
        socket.StartClient();
        socket.Dispose();
    }
}

class SynchronousSocketClient : IDisposable
{
    private string ip;
    private int port;
    private object data;
    public StreamWriter log;
    public event EventHandler Disposed;
    public SynchronousSocketClient(string ip, int port, string logfile, object data)
    {
        this.ip = ip;
        this.port = port;
        this.data = data;
        openLog(logfile);
    }
    public void openLog(string logfile)
    {
        log = new StreamWriter(logfile, true);
    }
    public void Dispose()
    {
        log.Close();
        if (this.Disposed != null)
            this.Disposed(this, EventArgs.Empty);
    }
    // Convert an object to a byte array
    private byte[] Serialize(object obj)
    {
        Stream stream = new MemoryStream();
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(stream, obj);
        byte[] b = null;
        b = new byte[stream.Length];
        stream.Position = 0;
        stream.Read(b, 0, (int)stream.Length);
        stream.Close();
        return b;
    }
    public void StartClient()
    {
        // Data buffer for incoming data.
    byte[] bytes = new byte[1024];
    // Connect to a remote device.
    try {
        // Establish the remote endpoint for the socket.
        // This example uses port 11000 on the local computer.
        IPHostEntry ipHostInfo = Dns.GetHostEntry(ip);
        IPAddress ipAddress = ipHostInfo.AddressList[0];
        IPEndPoint remoteEP = new IPEndPoint(ipAddress,port);
        // Create a TCP/IP  socket.
        Socket sender = new Socket(AddressFamily.InterNetwork, 
            SocketType.Stream, ProtocolType.Tcp );
        // Connect the socket to the remote endpoint. Catch any errors.
        try {
            sender.Connect(remoteEP);
            log.WriteLine(DateTime.Now+": Socket connected to {0}",
                sender.RemoteEndPoint.ToString());
            // Encode the data string into a byte array.
            byte[] msg = Serialize(data);
            // Send the data through the socket.
            int bytesSent = sender.Send(msg);
            // Receive the response from the remote device.
            int bytesRec = sender.Receive(bytes);
            log.WriteLine(DateTime.Now + ": {0}",
                Encoding.Unicode.GetString(bytes,0,bytesRec));
            // Release the socket.
            sender.Shutdown(SocketShutdown.Both);
            sender.Close();
        } catch (ArgumentNullException ane) {
            log.WriteLine(DateTime.Now + ": ArgumentNullException : {0}", ane.ToString());
        } catch (SocketException se) {
            log.WriteLine(DateTime.Now + ": SocketException : {0}", se.ToString());
        } catch (Exception e) {
            log.WriteLine(DateTime.Now + ": Unexpected exception : {0}", e.ToString());
        }
    } catch (Exception e) {
        log.WriteLine(DateTime.Now+": "+e.ToString());
    }
    }
}
//服务器:

class ProgramServer
{
    static void Main(string[] args)
    {
        NetworkSocket socket = new NetworkSocket(nwsocketport);
        socket.Start();
    }
}

public class StateObject
{
    // Client socket.
    public Socket workSocket = null;
    // Size of send buffer.
    public const int sBufferSize = 1024;
    // send buffer.
    public byte[] sBuffer = new byte[sBufferSize];
    // Received data object;
    public object data = null;
    // bytes read so far
    public int bytesRead;
    //receive buffer
    public byte[] rBuffer;
}
public class NetworkSocket
{
    private int port;
    Socket listener;
    IPEndPoint localEndPoint;

    public NetworkSocket(int port) {
        this.port = port;
    }
    public void Start() {
        // Establish the local endpoint for the socket.
        IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
        IPAddress ipAddress = ipHostInfo.AddressList[1];
        localEndPoint = new IPEndPoint(ipAddress, port);
        // Create a TCP/IP socket.
        listener = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp );
        //set socket timeouts
        listener.SendTimeout = 5000;
        listener.ReceiveTimeout = 5000;
        // Bind the socket to the local endpoint and listen for incoming connections.
        try {
            listener.Bind(localEndPoint);
            listener.Listen(1);
            listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
        } catch (Exception e) {
            Console.WriteLine(e.ToString());
        }
    }
    public void AcceptCallback(IAsyncResult ar) {
        // Signal the main thread to continue.
        //allDone.Set();
        // Get the socket that handles the client request.
        Socket listener = (Socket) ar.AsyncState;
        Socket handler = listener.EndAccept(ar);
        // Create the state object.
        StateObject state = new StateObject();
        // Data buffer for incoming data.
        state.rBuffer = new Byte[listener.ReceiveBufferSize];
        state.workSocket = handler;
        handler.BeginReceive(state.rBuffer, 0, state.rBuffer.Length, 0,
            new AsyncCallback(ReadCallback), state);
        try
        {
            listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }
    public void ReadCallback(IAsyncResult ar) {
        // Retrieve the state object and the handler socket
        // from the asynchronous state object.
        StateObject state = (StateObject) ar.AsyncState;
        Socket handler = state.workSocket;
        //handler.ReceiveTimeout = 2000;
        // Read data from the client socket. 
        state.bytesRead = handler.EndReceive(ar);
        Send(handler, "paket successfully tranferred");
        state.data = Deserialize(state.rBuffer);
        bool xmlDoc = true;
        try
        {
            XDocument.Parse(state.data.ToString());
        }
        catch
        {
            xmlDoc = false;
        }
        if (xmlDoc)
            XMLHandler.update(state.data.ToString());

    }
    private void Send(Socket handler, String data) {
        // Convert the string data to byte data using ASCII encoding.
        byte[] byteData = Encoding.Unicode.GetBytes(data);
        // Begin sending the data to the remote device.
        handler.BeginSend(byteData, 0, byteData.Length, 0,
            new AsyncCallback(SendCallback), handler);
    }
    private void SendCallback(IAsyncResult ar) {
        try {
            // Retrieve the socket from the state object.
            Socket handler = (Socket) ar.AsyncState;
            // Complete sending the data to the remote device.
            int bytesSent = handler.EndSend(ar);
            Console.WriteLine("Sent {0} bytes to client.", bytesSent);
            handler.Shutdown(SocketShutdown.Both);
            handler.Close();
        } catch (Exception e) {
            Console.WriteLine(e.ToString());
        }
    }
    // Convert a byte array to an Object
    private object Deserialize(byte[] b)
    {
        MemoryStream stream = new MemoryStream(b);
        BinaryFormatter bf = new BinaryFormatter();
        object obj = bf.Deserialize(stream);
        stream.Close();
        return obj;
    }
    // convert object to byte array
    private byte[] Serialize(object obj)
    {
        Stream stream = new MemoryStream();
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(stream, obj);
        byte[] b = null;
        b = new byte[stream.Length];
        stream.Position = 0;
        stream.Read(b, 0, (int)stream.Length);
        stream.Close();
        return b;
    }
}
有谁能帮我解决这个问题吗?我没有Socket编程经验…

网络套接字-只是第一个消息总是完成

在您的ReadCallback中,您需要启动另一个BeginReceive,就像您在AcceptCallback方法中调用BeginAccept一样。

您的代码中更严重的问题是您希望每个ReadCallback接收一个完整的消息。实际上,您可以接收半个消息、一个字节或三个消息。