【问题标题】:Can a ListViewItem Tag property contain a Socket objectListViewItem 标记属性是否可以包含 Socket 对象
【发布时间】:2016-01-17 09:20:45
【问题描述】:

在我的服务器端,我设置了一个单线程代码,每次客户端连接时都会创建一个新的 Socket 对象。然后,我将从客户端获得的任何内容与连接到数据包处理程序的套接字一起传递,并在那里进行计算。在我的主窗体中,我有一个通过实体框架填充的列表视图,每当来自已注册计算机的数据包连接时,我都会更新列表视图。所以我的问题是,当我更新它时,我可以从数据包处理程序类中将套接字对象传递给我的列表视图的标记属性吗?

我的服务器端代码:

private void ReceivedCallback(IAsyncResult result)
    {
        Socket clientSocket = result.AsyncState as Socket;
        SocketError ER;
        try
        {
            int bufferSize = clientSocket.EndReceive(result, out ER);
            if (ER == SocketError.Success)
            {
                byte[] packet = new byte[bufferSize];
                Array.Copy(_buffer, packet, packet.Length);
                Console.WriteLine("Handling packet from IP:" + clientSocket.RemoteEndPoint.ToString());
                //Handle packet stuff here.
                PacketHandler.Handle(packet, clientSocket);
                _buffer = new byte[61144];
                clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceivedCallback, clientSocket);
                //clientSocket.BeginReceive(new byte[] { 0 }, 0, 0, 0, ReceivedCallback, clientSocket);
            }
            else
            {
                Console.WriteLine("No bytes received, we're closing the connection.");
                clientSocket.Close();
            }
        }catch(SocketException ex)
        {
            Console.WriteLine("We caught a socket exception:" + ex.Message);
            clientSocket.Close();
        }
    }

还有我的数据包处理程序类:

public static void Handle(byte[] packet, Socket clientSocket)
    {
        if (clientSocket.Connected)
        {
            if (packet.Length > 0)
            {
                IPEndPoint RemoteIP = (IPEndPoint)clientSocket.RemoteEndPoint;
                ushort packetLength = BitConverter.ToUInt16(packet, 0);
                ushort packetType = BitConverter.ToUInt16(packet, 2);
                ushort packetID = BitConverter.ToUInt16(packet, 4);
                Console.WriteLine("We received a packet of Type: {0}, ID: {1} FROM {2}", packetType, packetID, RemoteIP.ToString());

                if (packetType == 1)
                {
                    switch (packetID)
                    {
                        case 1://Check if computer is registered in the database
                            CheckRegisteredRequest request1 = new CheckRegisteredRequest(packet);
                            Console.WriteLine("We received (Case 1): " + request1.Text);
                            string Response = "";
                            bool found = false;
                            ServerDbContext database = new ServerDbContext();
                            foreach (computers pcs in database.computers)
                            {
                                if (pcs.name == request1.Text.Split(',')[0])
                                {
                                    found = true;
                                    if (pcs.computer_ip == request1.Text.Split(',')[1])
                                    {
                                        //We found a computer with that name and ip address
                                        Response = "true";
                                        CheckRegisteredResponse resp1 = new CheckRegisteredResponse(Response);
                                        clientSocket.Send(resp1.Data);
                                        computers registeredPC;
                                        var name = request1.Text.Split(',')[0];
                                        using (var ctx = new ServerDbContext())
                                        {
                                            registeredPC = ctx.computers.Where(c => c.name == name).FirstOrDefault<computers>();
                                        }
                                        if (registeredPC != null)
                                        {
                                            registeredPC.networkStatus = "online";
                                        }
                                        using (var ctx = new ServerDbContext())
                                        {
                                            ctx.Entry(registeredPC).State = System.Data.Entity.EntityState.Modified;
                                            ctx.SaveChanges();
                                        }
                                        addNewLog("Computer: " + request1.Text.Split(',')[0] + " came online - IP: " + request1.Text.Split(',')[1]);
                                        RaiseFeedback("PC: " + request1.Text.Split(',')[0] + " came online - IP: " + request1.Text.Split(',')[1]);
                                        break;
                                    }
                                    else
                                    {
                                        //We found a computer with that name but a different ip address, update it
                                        var name = request1.Text.Split(',')[0];
                                        var registeredPC = new computers();
                                        using (var ctx = new ServerDbContext())
                                        {
                                            registeredPC = ctx.computers.Where(c => c.name == name).FirstOrDefault<computers>();
                                        }
                                        if (registeredPC != null)
                                        {
                                            var ip = request1.Text.Split(',')[1];
                                            registeredPC.computer_ip = ip;
                                            registeredPC.networkStatus = "online";
                                        }

                                        using (var ctx = new ServerDbContext())
                                        {
                                            ctx.Entry(registeredPC).State = System.Data.Entity.EntityState.Modified;
                                            ctx.SaveChanges();
                                        }
                                        Response = "true";
                                        CheckRegisteredResponse resp1 = new CheckRegisteredResponse(Response);
                                        clientSocket.Send(resp1.Data);
                                        addNewLog("Computer: " + request1.Text.Split(',')[0] + " came online - IP: " + request1.Text.Split(',')[1]);
                                        RaiseFeedback("PC: " + request1.Text.Split(',')[0] + " came online - IP: " + request1.Text.Split(',')[1]);
                                        break;
                                    }
                                }
                            }
                            if (!found)
                            {
                                //There is no computer with that name in the database so send false
                                Response = "false";
                                CheckRegisteredResponse resp1 = new CheckRegisteredResponse(Response);
                                clientSocket.Send(resp1.Data);
                            }
                            break;... and so on....

所以我已经通过处理程序进行了尝试:

这是我的自定义事件处理程序 Args:

public class TextArgs : EventArgs
{
    #region Fields
    private string szMessage;
    private Socket _sockets123;
    #endregion Fields

    #region ConstructorsH
    public TextArgs(string TextMessage,Socket sock)
    {
        if (sock != null)
        {
            _sockets123 = sock;
            szMessage = TextMessage;
        }
        else
        {
            szMessage = TextMessage;
        }
    }
    #endregion Constructors

    #region Properties
    public string Message
    {
        get { return szMessage; }
        set { szMessage = value; }
    }

    public Socket _socket
    {
        get { return _sockets123; }
        set { _sockets123 = value; }
    }
    #endregion Properties
}

这就是我在 PacketHandler 类中定义该处理程序的方式: 公共静态事件 LogsEventHandler 反馈;

    private static void RaiseFeedback(string p, Socket sock)
    {
        LogsEventHandler handler = Feedback;
        if (handler != null)
        {
            handler(null,new TextArgs(p,sock));
        }
    }

每当计算机注册或连接时,我都会执行以下操作:

RaiseFeedback("PC: " + request1.Text.Split(',')[0] + " came online - IP: " + request1.Text.Split(',')[1], clientSocket); 

RaiseFeedback("PC: " + request1.Text.Split(',')[0] + " came online - IP: " + request1.Text.Split(',')[1], null);

这两种方法的事件在我的主要形式中触发:

        private void OnFeedbackReceived(object sender, TextArgs e)
    {
        Invoke((MethodInvoker)delegate
            {
                UpdateComputers();
                UpdateGUI(e.Message,e._socket);
            }
        );            
    }

    public void UpdateGUI(string s, Socket sock)
    {
        LogBox.Text += s;
        LogBox.AppendText(Environment.NewLine);
        using (var context = new ServerDbContext())
        {
            var PCInfo = context.viewUsersInfo;
            dataGridView1.DataSource = PCInfo.ToList();
        }
        if (sock != null)
        {
            ListViewItem item = ComputersList.FindItemWithText(s.Split(':')[1].ToString());
            item.Tag = sock;
        }
    }

【问题讨论】:

  • 标签是对象。当你尝试时发生了什么?
  • 我试过这样: ListViewItem item = ComputersList.FindItemWithText(s.Split(':')[1].ToString()); item.Tag = 袜子;但由于某种原因,它无法获取该对象,我正在通过 EventHandler 将对象正确传递给它。
  • 获取该对象不起作用你能解释一下吗?还显示您使用的代码?你把它扔回socket,对吧?另外:请不要在 cmets 中添加代码;而是编辑问题,它看起来不错并且很容易找到和阅读..Socket theSocket = null; if (lvi.Tag != null) theSocket = lvi.Tag as Socket; if (theSocket != null) ...
  • 好的,我已经更改了问题,并添加了正在发生的事情。
  • 我看到你是如何设置标签的,但我看不到你把它拉出来的地方。另外:这是 private Socket _socekt; 错字吗?还有:是 set { _socket = value; } //我在这里得到一个系统堆栈溢出异常 真正的问题是什么?显然你不能直接设置属性;通常它会被称为SocketTheSocket。 setter 是一个无限循环。尽可能用自动的 setter 和 getter 替换:public Socket MySocket { get; set;};

标签: c# sockets listview tags listviewitem


【解决方案1】:

问题:是的,你可以。 Control.Tag 是 object 类型,几乎可以容纳您选择的任何东西。

所以你可以写

Socket socket = someSocket;
ListViewItem item = listView1.FindItemWithText(someText);
if (item != null) item.Tag = socket; else Console.WriteLine(someText + " not found!);

并将其检索为:

if (item.Tag != null) someSocket = item.Tag AS socket;
if (someSocket  != null) ..

在检索演员表时是否成功,以及Socket 是否还活着且健康状况良好。

问题:您的代码中的 stackoverflow 是由于错误的短路属性造成的,您现在已经修复了该属性。一般来说,你只需要编写显式的 getter 和 setter,前提是它们实际上不仅仅是 gettin 和 setting。

他们可以注销测试数据、更新其他相关属性、进行检查或转换或做其他事情。

但如果都不需要,干脆不要创建私有字段并编写自动 getter 和 setter:

public Socket MySocket {get; set;}

还要注意naming convention 要求您提供capitalize 属性名称!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-19
    • 1970-01-01
    • 1970-01-01
    • 2021-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多