c# socket接收线程

本文关键字:线程 socket | 更新日期: 2023-09-27 18:13:20

我有一个套接字连接,我正在通过这个套接字发送数据。我所连接的服务器回答我的每一个正确的数据发送。我已经让消息工作,所以我收到的每条消息都有一个答案。有时,服务器喜欢将消息保留几秒钟,或者以不同的顺序发送。我的解决方案是生成一个线程,并让它围绕一个接收函数旋转。然而,使用MSDN上的套接字示例我有适合。它们使用一个简单的do/while循环结构。当我这样做的时候,我得到的是混乱的回复和/或不完整的数据。这是一个家庭作业,所以我必须手写客户端,而不是仅仅使用一个更容易的解决方案。这段代码可能有问题吗?我盯着它看太久了,我想我错过了一些简单的东西:

private static void ReceiveThread(Socket sock, ReceiverClass rc)
{
    // Create a socket and pass in parameter converted from object socket
    int receivedBytes = 0;
    do
    {
        // receive data from socket
        receivedBytes = sock.Receive(rc.buffer);
        byte[] formattedMsg = new byte[receivedBytes];
        Array.Copy(rc.buffer, formattedMsg, receivedBytes);
        rc.sb.Append("<LF><CR>" + System.Text.Encoding.ASCII.GetString(formattedMsg) + "'r'n");
    }
    while (receivedBytes > 0);
}

编辑,增加生成接收线程的函数。(这是太长了,但我计划让它漂亮,当我让愚蠢的东西工作):

    public void SendData(Socket sock)
    {
        // Set socket timeout
        sock.ReceiveTimeout = 4000;
        // Prepare file for IO operations
        string path = @"c:'Logs'Lab2.Scenario3.WurdingerO.txt";
        StreamWriter logWrite = File.AppendText(path);
        // Get local ip address:
        IPAddress ip = Dns.GetHostAddresses(Dns.GetHostName()).Where(address => address.AddressFamily == AddressFamily.InterNetwork).First();
        string portNum = ((IPEndPoint)sock.LocalEndPoint).Port.ToString();
        // response time for scenario 2 and 3
        int responseTime = 0;
        // Set up Stopwatch to keep track of time
        Stopwatch stpWatch = new Stopwatch();
        stpWatch.Start();
        // setup for logging class
        ReceiverClass rc = new ReceiverClass();
        // setup receiving thread
        Thread receiveThread = new Thread(delegate()
            {
                ReceiveThread(sock, rc);
            });
        receiveThread.Start();
        // Counter to call client operations
        for (int i = 0; i < MESSAGE_COUNT; i++)
        {
            string msTime = Convert.ToString(stpWatch.ElapsedMilliseconds);
            if (msTime.Length > 10)
            {
                string newMSTime = "";
                for (int t = 9; t >= 0; t++)
                {
                    newMSTime += msTime[t];
                }
                msTime = newMSTime;
            }
            Classes.RequestBuilder reqB = new Classes.RequestBuilder();
            byte[] sendMsg;
            switch (scenarioNo)
            {
                case 1:
                    sendMsg = reqB.MessageBuildScenarioOne(sock, msTime,
                        ip.ToString(), portNum, serverPort, serverIP, i);
                    break;
                case 2:
                    // set up response time delay
                    switch (i)
                    {
                        case 1:
                            responseTime = 1000;
                            break;
                        case 3:
                            responseTime = 3000;
                            break;
                        default: 
                            responseTime = 0;
                            break;
                    }
                    sendMsg = reqB.MessageBuildScenarioTwo(sock, msTime,
                        ip.ToString(), portNum, serverPort, serverIP, i, responseTime);
                    break;
                case 3:
                    // set up response time delay
                    switch (i)
                    {
                        case 1:
                            responseTime = 1000;
                            break;
                        case 3:
                            responseTime = 3000;
                            break;
                        default:
                            responseTime = 0;
                            break;
                    }
                    sendMsg = reqB.MessageBuildScenarioThree(sock, msTime,
                        ip.ToString(), portNum, serverPort, serverIP, i, responseTime);
                    break;
                default:
                    sendMsg = reqB.MessageBuildScenarioOne(sock, msTime,
                        ip.ToString(), portNum, serverPort, serverIP, i);
                    break;
            }
            try
            {
                sock.Send(sendMsg);
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message);
            }
        }
        // Socket shutdown
        sock.Shutdown(SocketShutdown.Send);
        receiveThread.Join();
        sock.Shutdown(SocketShutdown.Receive);
        string date = System.DateTime.Now.ToString("MMddyyyy");
        string time = System.DateTime.Now.ToString("HHmmss");
        logWrite.Write(rc.sb.ToString());
        logWrite.Write(date + "|" + time + "|0|0|");
        // Close log file
        logWrite.Close();
        System.Windows.Forms.MessageBox.Show("Finished");
    }

编辑:我在发送操作后放置了一个睡眠计时器,这解决了我遇到的问题。谢谢你!

c# socket接收线程

我想我也有类似的问题。

我使用Socket类发送JSON字符串,突然JSON。. NET将抛出异常。我检查了字符串,看到正在处理2个JSON(根)对象。然后我拼凑了一个最小的例子,发现套接字将隐藏*任何未读的数据(未读=没有。receive尚未被调用,并且。receive将清除隐藏)。

*stash:我不确定这是否是正确的术语。这对我来说很有意义。

这是我的测试。如果您想运行它,创建一个新的测试类并安装XUnit。

/// <summary>
/// Testing Net Sockets..
/// </summary>
/// <author>Jeff Hansen</author>
public class SocketTests
{
    /// <summary>
    /// The local endpoint for the server. There's no place like 127.0.0.1
    /// </summary>
    private IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1337);
    /// <summary>
    /// Tests that a call to .Receive will return all unread data.
    /// </summary>
    /// <author>Jeff Hansen</author>
    [Fact]
    public void ReceiveWillReadAllUnreadData()
    {
        // We expect to receive double data.
        const string expected = "HELLOHELLO";
        const string dataToSend = "HELLO";
        // Start the server in a background task.
        // We do this because the receive call is blocking.
        var bgTask = Task.Factory.StartNew(() =>
        {
            var server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                // Bind to the endpoint and start listening.
                server.Bind(endpoint);
                server.Listen(10); // 10 is max allowed connections in queue (I think)
                // Client connected, receive data
                var connectingClient = server.Accept();
                // So low-level we even get to allocate room for the data buffer manually.
                var buf = new byte[1024];
                // Hangs until data flows.
                var sz = connectingClient.Receive(buf); // This is the size of the data we just received.
                var data = Encoding.ASCII.GetString(buf, 0, sz); // We use the size to only grab what we need from the buffer.
                Console.WriteLine("Data received: {0}", data);
                // This is going to pass because we sent the data twice,
                // and the call to Receive would not be able to complete in time
                // for it to clear before more data becomes available.
                Assert.Equal(expected, data);
                /*
                 * BAM! Theory proven. We seriously had issues 
                 * because we didn't understand how it worked. This is why you usually end
                 * your transmission with a newline.
                 */
                Console.WriteLine("Server closing");
                server.Close();
            }
            catch (Exception e)
            {
                // Make sure we close the server.
                server.Close();
                throw;
            }
        });
        // Create a client socket and connect it to the server.
        // The server thread should have started it up by now.
        var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        client.Connect(endpoint);
        // Get the bytes of our string
        var buffer = Encoding.ASCII.GetBytes(dataToSend);
        // Send it out twice. This happens faster than the server will process it,
        // so the data is stacking up. You would THINK that .Receive would
        // simply return the first data sent to it, and the next time .Receive is called
        // return the next. But that's not how it works, apparently.
        client.Send(buffer);
        client.Send(buffer);
        // Wait for the server to finish whatever it's doing.
        try
        {
            // We give it 3000ms to complete.
            bgTask.Wait();
        }
        catch (AggregateException ag)
        {
            // Throw any esceptions that were thrown in the background thread.
            ag.Handle(ex => { throw ex; });
        }
        // Close the client socket.
        client.Close();
    }
}

我们通过用换行符分隔数据来解决这个问题。

有趣的事实:我正在摆弄TcpClient,发现如果我不向流中写入换行符,它就不会发送任何东西-它只是挂在那里。不过可能是局部问题。有人愿意详细说明一下吗?