【问题标题】:Continuously read data from tcp server with specified time interval以指定的时间间隔从 tcp 服务器连续读取数据
【发布时间】:2016-11-05 23:32:49
【问题描述】:

我需要实现 tcp socket Client。我们必须以特定的时间间隔从服务器 tcp 套接字接收数据。如果我们从客户端发出连接请求,则连接不会断开。每当服务器发送数据时,我们都必须接收数据。我尝试过异步客户端通信来自 MSDN 网站。但是Receive回调函数是在receive方法中调用的,所以我们必须无间隔地从服务器接收数据。如果没有连续接收到数据,则连接将进入接收完成并断开连接。

谁能帮帮我...谢谢提前

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Threading;
using System.Configuration;
using System.Net;
using System.IO;
using System.Data.OleDb;
using System.Data.SqlClient;
using System.Transactions;

namespace ClientSocket
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }



        public class StateObject
        {
            public Socket workSocket = null;
            public const int BufferSize = 5176;
            public byte[] buffer = new byte[BufferSize];
            public StringBuilder sb = new StringBuilder();

        }

        public class AsynchronousClient
        {
            public const int port = 8095;

            public static ManualResetEvent connectDone =
                new ManualResetEvent(false);
            public static ManualResetEvent sendDone =
                new ManualResetEvent(false);
            public static ManualResetEvent receiveDone =
                new ManualResetEvent(false);

            public static String response = String.Empty;

            public static void StartClient()
            {
                try
                {
                    IPAddress ipAddress = IPAddress.Parse("192.168.1.89");
                    IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

                    Socket client = new Socket(AddressFamily.InterNetwork,
                        SocketType.Stream, ProtocolType.Tcp);

                    client.BeginConnect(remoteEP,
                        new AsyncCallback(ConnectCallback), client);

                    connectDone.WaitOne();
                    client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

                    //Send(client, Msg + "<EOF>");
                    //sendDone.WaitOne();

                    Receive(client);
                    receiveDone.WaitOne();

                    MessageBox.Show(response, "Final Response received");


                    //Send(client, "Data From Client" + "<EOF>");
                    //sendDone.WaitOne();

                    //client.Shutdown(SocketShutdown.Both);
                    //client.Close();
                }
                catch (SocketException e)
                {
                    MessageBox.Show(e.Message);
                }
                //finally
                //{
                //    response = string.Empty;
                //}
            }

            public static void ConnectCallback(IAsyncResult ar)
            {
                try
                {
                    Socket client = (Socket)ar.AsyncState;

                    client.EndConnect(ar);

                    MessageBox.Show(string.Concat("Socket connected to ",
                        client.RemoteEndPoint.ToString()));

                    connectDone.Set();
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.ToString());
                }
            }

            public static void Receive(Socket client)
            {
                try
                {
                    StateObject state = new StateObject();
                    state.workSocket = client;

                    client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                        new AsyncCallback(ReceiveCallback), state);

                }
                catch (Exception e)
                {
                    MessageBox.Show(e.ToString());
                }
            }

            public static void ReceiveCallback(IAsyncResult ar)
            {
                MessageBox.Show("Receivecallback");
                StateObject state = (StateObject)ar.AsyncState;
                state.sb.Clear();
                Socket client = state.workSocket;

                try
                {
                    // Read data from the remote device.
                    int bytesRead = client.EndReceive(ar);

                    if (bytesRead > 0)
                    {

                        state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
                        MessageBox.Show(state.sb.ToString(), "Data");


                        client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                            new AsyncCallback(ReceiveCallback), state);
                    }
                    else
                    {
                        //if (state.sb.Length > 1)
                        //{
                        //    response = state.sb.ToString();
                        //}
                        //////Send(client, "NG", "Error");
                        //receiveDone.Set();
                        client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);

                        //state.sb.Clear();
                    }
                }
                catch (Exception e)
                {
                    Send(client, "NG", e.Message.ToString());
                    MessageBox.Show(e.ToString());
                }
            }

            public static void Send(Socket client, String data, String ErrorMessage)
            {
                byte[] Status = Encoding.ASCII.GetBytes(data);
                byte[] errorMessage = Encoding.ASCII.GetBytes(ErrorMessage);
                byte[] statusSize = new byte[240];

                int i = new int();
                foreach (var ST in Status)
                {
                    i++;
                    if (i == 1)
                        statusSize[0] = ST;
                    if (i == 2)
                        statusSize[1] = ST;
                }
                if (data.Equals("NG"))
                {
                    int j = 2;
                    foreach (byte em in errorMessage)
                    {
                        statusSize[j] = em;
                        j++;
                    }
                }

                client.BeginSend(statusSize, 0, statusSize.Length, 0,
                    new AsyncCallback(SendCallback), client);
            }

            public static void SendCallback(IAsyncResult ar)
            {
                try
                {
                    Socket client = (Socket)ar.AsyncState;

                    int bytesSent = client.EndSend(ar);
                    MessageBox.Show(string.Concat("Sent bytes to server.", bytesSent.ToString()));
                    //SocketConnected(client);
                    sendDone.Set();
                    //MessageBox.Show("Send Callback");

                }
                catch (Exception e)
                {
                    MessageBox.Show(e.ToString());
                }
            }
            public static bool SocketConnected(Socket s)
            {
                bool part1 = s.Poll(1000, SelectMode.SelectRead);
                bool part2 = (s.Available == 0);
                if (part1 && part2)
                    return false;
                else
                    return true;
            }


        }

        private void btnConnect_Click(object sender, EventArgs e)
        {

            AsynchronousClient.StartClient();
        }



        }

    }
}

【问题讨论】:

  • 我猜你已经开始实现这样的间隔例程了。你会介意张贴吗?这将是一个很好的起点。
  • 我附上了我的代码。它只收到第一个响应。如果服务器在一段时间后发送数据,那么我如何从这个代码中获取数据。
  • 任何人都可以根据上面的代码帮助我

标签: c# sockets tcpclient windows-applications


【解决方案1】:

您的问题是,对于接收,对方正在确定发送数据的数量和时间。您应该创建某种请求消息,但您必须继续接收。

  • 所以每隔一段时间向服务器发送一个数据请求。
  • 继续接收。

【讨论】:

    【解决方案2】:

    在新线程中创建套接字客户端,然后永远开始读取。

    using System;
    using System.Threading;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Collections;
    
    namespace TCPClient
    {
    class TCPClient
    {
    
        [STAThread]
        static void Main(string[] args)
        {
            TCPClient client = null;
            client = new TCPClient("filename");
    
        }
    
        private String m_fileName=null;
        public TCPClient(String fileName)
        {
            m_fileName=fileName;
            Thread t = new Thread(new ThreadStart(ClientThreadStart));
            t.Start();
        }
    
        private void ClientThreadStart()
        {
            Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
            clientSocket.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"),31001));
    
            // Send some data if erquired.
            clientSocket.Send(Encoding.ASCII.GetBytes("testdata"));
    
            // Receive the data whenver available.
            while(1)
            {
            byte [] data = new byte[1024];
            clientSocket.Receive(data);
            int length=BitConverter.ToInt32(data,0);
    
        //check if  you have received all the data and sleep for time interval. with Sleep(timeInterval), Do only after you have received all available data for instance.
            }
    
            clientSocket.Close();
        }
    
    }
    

    }

    【讨论】:

    • 你不应该在接收循环中休眠。这最终会溢出接收缓冲区,或者它可能会在发送时阻塞服务器。
    • @JeroenvanLangen 谢谢!你是对的,它可能会溢出接收缓冲区。但不会阻止服务器。因为tcp服务器不等待客户端接收所有数据。我会相应地修改答案。 (Y)
    • 是的,它可以阻塞服务器,因为 TCP 是一个流。当接收缓冲区已满时,服务器将收到一条消息(tcp 层),表明客户端接收缓冲区已满(带有tcp set window size 的内容),并且您的服务器(如果实施阻塞(默认))将阻塞执行。跨度>
    • @JeroenvanLangen 我不知道这一点,现在学会了。谢谢!
    • 如果您自己实现服务器,您可能需要检查non-blocking 套接字。当客户端接收缓冲区已满 (WOULD_BLOCK) 时,您将收到错误代码。这样您就可以定义自己的循环进行重新发送。这对于具有许多客户端(通过 Internet)的服务器很有用。每次套接字阻塞时,它都会消耗一个线程。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-02
    相关资源
    最近更新 更多