本文介绍了用于操作字典的 TCP-IP 客户端-服务器应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个客户端-服务器程序.

I am writing a Client-server program.

服务器将保存一个字典,客户端可以向字典添加更新键值.

The Server would hold a dictionary, and clients are able to add an update key-values to the dictionary.

假设客户端-'A' 添加了一个项目 (1, 111).当另一个客户端-'B'想要更新(1, 111)的值时,它必须寻求'A'的确认,反之亦然.

Suppose a client-'A' adds an item (1, 111). When another client-'B' wants to update the value of (1, 111), it has to seek a confirmation from 'A', and vice versa.

请看下面的程序:

using MyClientServerLib;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MyServerProgram
{
    class ServerProgram
    {
        static Dictionary<string, KeyValue> KeyValueDictionary;
        static Dictionary<string, ClientClass> ClientDictionary;

        static void Main(string[] args)
        {
            Console.Title = "Server";
            Console.WriteLine("Server program started...");

            KeyValueDictionary = new Dictionary<string, KeyValue>();
            ClientDictionary = new Dictionary<string, ClientClass>();

            string ipAddress = "127.0.0.1";
            int portNo = 2000;

            IPAddress ip = IPAddress.Parse(ipAddress);
            TcpListener listener = new TcpListener(ip, portNo);

            // poll for clients in a 2nd thread
            Thread thread = new Thread(delegate()
            {
                ServerProgram.PollIncomingClientConns(listener);
            });

            thread.Start();
        }

        #region catching client connections
        static void PollIncomingClientConns(TcpListener listener)
        {
            listener.Start();

            try
            {
                bool keepRunning = true;

                while (keepRunning)
                {
                    ClientClass client = new ClientClass(listener);

                    ClientDictionary.Add(client.ID, client);

                    Thread thread = new Thread(delegate()
                    {
                        ServerProgram.ReadFromClient(client);
                    });
                    thread.Start();
                }
            }
            catch (Exception ex)
            {
                var inner = ex.InnerException as SocketException;
                if (inner != null && inner.SocketErrorCode == SocketError.ConnectionReset)
                    Console.WriteLine("Disconnected");
                else
                    Console.WriteLine(ex.Message);

                listener.Stop();
            }
        }
        #endregion

        static void ReadFromClient(ClientClass client)
        {
           try
            {
                ClientClass origClient = null;

                while (client.Tcp.Connected)
                {
                    string str = client.ReadString();

                    switch(str)
                    {
                        case Commands.AddKeyValue:
                            string key = client.ReadString();
                            string val = client.ReadString();
                            KeyValue keyValue = new KeyValue(client.ID, key, val);
                            KeyValueDictionary.Add(key, keyValue);
                            Console.WriteLine(keyValue.ToString() + " added.");
                            break;

                        case Commands.ListKeys:
                            if (KeyValueDictionary.Keys.Count > 0)
                            {
                                foreach (string key1 in KeyValueDictionary.Keys)
                                {
                                    client.Write("(" + key1 + "," + KeyValueDictionary[key1].Value + ")\t");
                                }
                            }
                            else
                            {
                                client.Write("No KV");
                            }
                            break;

                        case Commands.UpdateValue: //obtain update requester client-ID
                            client.Key = client.ReadString(); //read key
                            client.Value = client.ReadString(); //read val

                            KeyValue oldKeyVal = null;

                            bool currClientFound = KeyValueDictionary.TryGetValue(client.Key, out oldKeyVal); //search the dictionary with the client name

                            if (currClientFound) //if found
                            {
                                if (oldKeyVal.ClientID.Equals(client.ID))//if rem requested by same client...
                                {
                                    KeyValueDictionary[client.Key].Value = client.Value;
                                    client.Write(client.Key + " is updated.");
                                }
                                else //if rem requested by a different client...
                                {
                                    //get the original client
                                    bool origClientFound = ClientDictionary.TryGetValue(oldKeyVal.ClientID, out origClient); //search the dictionary with the client name

                                    if (origClientFound)
                                    {
                                        origClient.Write(client.ID + " wants to change " + oldKeyVal.ToString() + "(y/n)");
                                    }
                                }
                            }
                            break;

                        case Commands.Yes:
                            Console.WriteLine(client.Key + ", " + client.Value);
                            KeyValueDictionary[client.Key].Value = client.Value;
                            client.Write(client.Key + " is updated.");
                            break;
                    }
                }
            }
            catch
            {
                client.Disconnect();
            }
        }
    }
}

问题出在 case Commands.UpdateValuecase Commands.Yes.

当客户端在之前的迭代中请求更新时,键值对与客户端实例一起保存.然后,在下一次迭代中,当另一个客户端发送确认时,更新键值对.

When a client requests for an update in previous iteration, the key-value pair is saved with the client-instance. Then, in the next iteration, when the other client sends an affirmation, the key-value pair is updated.

但是,在下一次迭代中,client.Key 显示 null.因此 case Commands.Yes 失败了.

But, in the next iteration, client.Key is showing null. Hence case Commands.Yes is failing.

我该如何解决这个问题?

How can I solve this issue?

其他源代码文件:

  1. ClientProgram.cs
  2. ClientClass.cs

推荐答案

我通过使保持键和值的变量保持静态来解决这个问题:

I have solve this problem by making key and value holding variables static:

 class ServerProgram
 {
      static stKey;
      static stValue;

      ....
      ....
                    case Commands.UpdateValue: //obtain update requester client-ID
                        stKey = client.ReadString(); //read key
                        stValue = client.ReadString(); //read val

                        ....
                        ....

                    case Commands.Yes:
                        Console.WriteLine(stKey + ", " + stValue);
                        KeyValueDictionary[stKey].Value = stValue;
                        client.Write(stKey + " is updated.");
                        break;

     }

这篇关于用于操作字典的 TCP-IP 客户端-服务器应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 07:07