【问题标题】:C# sockets: can't read after writing to socketC# 套接字:写入套接字后无法读取
【发布时间】:2014-02-28 13:42:43
【问题描述】:

在我的客户端/服务器应用程序中,我的客户端将与服务器进行通信以实现 2 个功能:客户端将向服务器请求数据或发送数据以便服务器将其保存。我对这两种方法都使用了一个套接字,并且要使用的方法由发送的第一个字节定义。如果第一个字节为“1”,则表示请求数据。如果为“2”,则发送数据(数据字节在“2”字节之后发送)。它非常适合发送数据。但是当我请求数据时,只要我不读取客户端中的套接字流,它就可以工作。就像我让客户端在发送数据后读取数据,服务器将没有数据可读取,并且在尝试读取数据时它只是崩溃。

这是我的服务器代码:

private const int BufferSize = 1024;
NetworkStream netstream = null;
byte[] RecData = new byte[BufferSize];
int RecBytes;

try {
     netstream = clientSocket.GetStream();
     int totalrecbytes = 0;

     using (MemoryStream ms = new MemoryStream()) {
         //When I get here, there is no data to read
         while ((RecBytes = netstream.Read(RecData, 0, RecData.Length)) > 0) {
             ms.Write(RecData, 0, RecBytes);
             totalrecbytes += RecBytes;
         }

         byte[] bytes = ms.ToArray();
         byte b = bytes[0];

         switch (b) {
             case 1:

             //Here I gather data and put it in "stream" variable


             byte[] SendingBuffer = null;
             int NoOfPackets = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(stream.Length) / Convert.ToDouble(BufferSize)));
             int TotalLength = (int)stream.Length, CurrentPacketLength, counter = 0;
             for (int i = 0; i < NoOfPackets; i++) {
                 if (TotalLength > BufferSize) {
                     CurrentPacketLength = BufferSize;
                     TotalLength = TotalLength - CurrentPacketLength;
                 }
                 else
                     CurrentPacketLength = TotalLength;
                 SendingBuffer = new byte[CurrentPacketLength];
                 stream.Read(SendingBuffer, 0, CurrentPacketLength);
                 netstream.Write(SendingBuffer, 0, (int)SendingBuffer.Length);
             }
             netstream.Flush();


         }
         catch (Exception e) {
             Console.WriteLine("EXCEPTION:\n" + e.ToString());
         }

         break;
     case 2:              
         //Code to read data

         break;
     }
 }
 netstream.Close()
 clientSocket.Close();

这是我的客户端代码:

using (System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient()) {

    string returnData = "";

    IAsyncResult ar = clientSocket.BeginConnect("127.0.0.1", 8080, null, null);
    System.Threading.WaitHandle wh = ar.AsyncWaitHandle;
    try {
        if (!ar.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5), false)) {
            clientSocket.Close();
            Console.WriteLine("Timeout");
            return;
        }

        System.Net.Sockets.NetworkStream serverStream = clientSocket.GetStream();

        byte b = 1;

        byte[] outStream = { b };
        serverStream.Write(outStream, 0, outStream.Length);
        serverStream.Flush();

        //If I comment following lines, the server can read sent data, but server can't otherwise
        byte[] RecData = new byte[1024];
        int RecBytes;
        int totalrecbytes = 0;
        MemoryStream MS = new MemoryStream();
        while ((RecBytes = serverStream.Read(RecData, 0, RecData.Length)) > 0) {
            MS.Write(RecData, 0, RecBytes);
            totalrecbytes += RecBytes;
        }
        serverStream.Close();
        clientSocket.Close();
        clientSocket.EndConnect(ar);

    }
    catch (Exception ex) {
        Console.WriteLine("Exceção: " + ex.ToString());
    }
    finally {
        wh.Close();
    }
}

那么,如何将数据发送到服务器并读取响应? (我什至尝试在发送数据后让线程进入睡眠状态,但没有成功。) 提前致谢。

编辑: 通过一些调试消息,我发现服务器确实读取了发送的“1”字节,但不知何故它卡在了 while 循环中,比如,服务器只是停在那里,没有更多的循环,也没有离开 while 循环。我看到在while循环内的控制台中写入“循环”之后,也在控制台中写入读取字节。它写了一次“循环”,然后读取字节。

【问题讨论】:

    标签: c# sockets


    【解决方案1】:

    这段代码让我担心:

         //When I get here, there is no data to read
         while ((RecBytes = netstream.Read(RecData, 0, RecData.Length)) > 0) {
             ms.Write(RecData, 0, RecBytes);
             totalrecbytes += RecBytes;
         }
    

    您正在阅读,直到客户端关闭连接(或关闭发送,您不这样做)。但是客户端只有在服务器回复后才会关闭。服务器回复永远不会到来。这是一个僵局。

    解决方案:读取单个字节以确定请求命令 (b)。

    与问题无关,您的“打包”发送 (NoOfPackets, ...) 似乎没有任何用途。只需使用Stream.Copy 写。 TCP 没有数据包。

    更好的解决方案是放弃自定义 TCP 协议并使用 HTTP 库。所有这些担忧都会烟消云散。您的代码存在各种小问题,这些问题在 TCP 代码中很常见。

    【讨论】:

    • 完美。就是这样。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2015-08-28
    • 2017-07-22
    • 1970-01-01
    • 2013-11-27
    • 2015-05-08
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多