当前位置: 首页 > 知识库问答 >
问题:

C#套接字:写入套接字后无法读取

隗锐进
2023-03-14

在我的客户端/服务器应用程序中,我的客户端wiil与服务器通信有两个功能:客户端要么向服务器请求数据,要么发送数据,以便服务器保存。我对这两种方法都使用一个套接字,要使用的方法由发送的第一个字节定义。如果第一个字节是“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();
    }
}

那么,我如何向服务器发送数据并读取响应呢?(我甚至尝试在发送数据后让线程Hibernate,但没有成功。)提前感谢。

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

共有1个答案

曹沛
2023-03-14

这段代码让我担心:

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

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

解决方案:读取一个字节来确定请求命令(< code>b)。

与问题无关,您的“打包”发送(< code>NoOfPackets,...)似乎没有任何作用。只需使用< code>Stream。复制进行编写。TCP没有数据包。

更好的解决方案是放弃自定义TCP协议并使用HTTP库。所有这些担忧都消失了。您的代码中存在各种较小的问题,这些问题在TCP代码中非常典型。

 类似资料:
  • 我转向你,在这件事上我一直把头撞在墙上。 我正在做一个小的socket编程,我可以看到当我把它放出来。println(“…”)while循环之前的代码行(in.readLine())它工作正常,但我需要它位于循环内部。 说清楚一点,我没有看到任何错误。我只是看不到此应用程序的客户端显示文本。它看起来好像在工作,但事实并非如此。此外,我也不控制该应用程序的客户端,它由通过TCP连接到此套接字侦听器应

  • socket_read和socket_recv之间有什么区别?我正在尝试使用PHP套接字,但使用socket_read时收到了以下警告: 请帮帮我!

  • 我正在尝试用套接字从客户端向服务器写入一个结构。 结构是: 这两个程序(服务器、客户机)的结构是相同的,并且这两个程序的结构是相同的。 客户端程序: 结构R*r; 马洛克.. ...(用数据填充结构) write(socket_fd,(void*)r,size of(R)); 服务器程序: 结构R*r; 马洛克.. read(client_fd,(R*)r,size of(R)); 这不是将结构从

  • 我正在尝试使用java套接字构建一个简单的多客户端聊天应用程序。我这样做的方式是,让一个客户机类连接到一个服务器类,该服务器类等待客户机连接,并创建一个新线程来处理该客户机(套接字连接在那里被读取和写入)。客户端还读取和写入到该线程的套接字连接。但是,当客户机写入套接字的输出流时,服务器不会响应。这里发布了一个类似的问题: 您可以同时写入套接字输入和输出流吗? 这里的一个答案是,只要在单独的线程上

  • 问题内容: 我试图理解SocketChannels和NIO。我知道如何使用常规套接字,以及如何制作一个简单的每客户端线程服务器(使用常规阻塞套接字)。 所以我的问题是: 什么是SocketChannel? 当使用SocketChannel而不是Socket时,我还能得到什么呢? 通道和缓冲区之间是什么关系? 什么是选择器? 文档中的第一句话是。那是什么意思? 我也阅读了本文档,但是不知何故…… 问

  • 我使用一个具有双向通信的套接字设置了一个客户端-服务器模型。 应该是这样的:1。客户端-发送单词数组2。服务器-读取单词数组3。服务器-发送布尔值4。客户端-读取布尔值5。客户端-发送图像6。服务器读取图像 这个过程在一个循环中,与第一次迭代完美配合,但在第二次迭代中,我得到了以下错误: JAVA网SocketException:软件导致的连接中止:套接字写入错误 我认为发生的是,当服务器返回到读