实施C#客户端-服务器以保持游戏数据同步时出现问题 [英] Problem implementing C# Client-Server to keep game data in sync

查看:122
本文介绍了实施C#客户端-服务器以保持游戏数据同步时出现问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经花了一段时间了(比预期的要长得多),但似乎仍然无法让客户端服务器使用C#.我认为主要的问题是我对C#中的套接字了解不多(我可以在Java中实现这一点没问题).

任何发现我的错误或帮助我了解如何正确实施的帮助将不胜感激.您将如何实现以下我的任何一个功能的代码示例将是很棒的:)

目标是将多个客户端连接到单个服务器.每个客户端可以将数据更新/更改发送到服务器,然后服务器将这些更新中继到所有其他客户端.这应该很简单,对吧?

服务器将跟踪列表中所有当前连接的客户端以及从连接中获取的TcpClient对象.

以下代码片段主要是线程的入口点,应该执行以下操作:

服务器端:
>接受新客户
>从客户端接收数据
>将数据发送给客户

客户端:
>将数据发送到服务器
>从服务器接收数据

I''ve been working on this for a while (much longer than anticipated) and still can''t seem to get a client-server working with C#. I think the main issue is my poor understanding of sockets in C# (I could implement this in Java no problem).

Any help finding my error(s) or helping me understand how to implement it properly would be appreciated. A code sample of how you would implement any one of my functions below would be great :)

The goal is to have multiple clients connected to a single server. Each client can send data updates/changes to the server, which then relays those updates to all other clients. This should be simple, right?

The server tracks all currently connected clients in a list along with the TcpClient object acquired from the connection.

The following code snippets are mostly entry points for threads and are supposed to do the following:

Server Side:
> Accept new clients
> Receive data from client
> Send data to clients

Client Side:
> Send data to server
> Receive data from sever

//Server Thread Entry Point: Waiting for client connections
        private void acceptClientConnection()
        {
            // Create a TCP/IP listener.
            TcpListener tcpListener = new TcpListener(IPAddress.Any, 3000);
            tcpListener.Start();

            //start listening for incomming connections from clients
            while (true)
            {
                //Wait for incoming client connection
                TcpClient client = tcpListener.AcceptTcpClient();

                //Save connection (launches new thread that waits for client msgs)
                clients.AddLast(new ConnClient(client, clients.Count));

                Console.WriteLine("SERVER: client connected to server");
            }
        }


到目前为止,还没有问题,但是我可以肯定这里有问题:以下代码是服务器处理来自客户端的传入数据的地方. (这在一个线程中运行;每个客户端一个线程).收到的更改将保存在队列中,并由另一个线程处理.

我觉得这段代码应该阻止,并等待来自客户端的消息,但是我不认为这种情况正在发生.


No problems so far, but I''m pretty sure I have issues here: The following code is where the server handles in-coming data from the clients. (This is run in a thread; one thread per client). The changes received are saved in a queue and are processed by another thread.

I feel this code should block, and wait for a message from the client, but I don''t think that is happening.

//Comm Thread Entry Point
            private void handleClientComm()
            {
                while (true)
                {
                    //handle incomming messages
                    if (conn.Connected)
                    {
                        Console.WriteLine("SERVER: still connected, reading stream");
                        //Get data from stream
                        byte[] data = ReadToEnd(conn.GetStream());

                        lock (dataChanges)
                        {
                            //add data to the change list
                            dataChanges.AddLast(new Pair<int, byte[]>(clientIndex, data));

                            //wake up any threads waiting on data
                            Monitor.PulseAll(dataChanges);
                        }
                    }
                    else Console.WriteLine("SERVER: not connected");
                }
            }



conn ==保存的TcpClient对象.
ReadToEnd(Stream)是我从响应复制到此处其他人问题的函数.我不能保证它的正确性...

以下是实际将更新发送给客户端的代码:
我相信它可以按预期工作.



conn == the saved TcpClient object.
ReadToEnd(Stream) is a function I copied from a response to someone else question on here. I can''t guarantee its correctness...

The following is the code that actually sends the updates to the clients:
I believe its working as intended.

//Synch Data Thread Entry Point
        private void synchData() 
        {
            while (true)
            {
                lock (dataChanges)
                {
                    //wait for data if there isn't any
                    Console.WriteLine("SERVER: waiting for data to synch");
                    while (dataChanges.Count == 0)
                        Monitor.Wait(dataChanges);

                    //send updates to all the clients
                    LinkedList<ConnClient>.Enumerator itr = clients.GetEnumerator();
                    for (int i = 0; i < clients.Count; i++ )
                    {
                        itr.MoveNext();
                        if(i == dataChanges.First.Value.index)
                            continue; // no need to send change data to the client that made the change

                        //send data to client
                        itr.Current.sendDataUpdate(dataChanges.First.Value.data);
                    }
                    dataChanges.RemoveFirst();
                    Console.WriteLine("SERVER: data change synched");
                }
            }
        }




and

//send data update to client (called from a separate thread)
            public void sendDataUpdate(byte[] data)
            {
                //handle incomming messages
                if (conn.Connected)
                {
                    //send data to the client
                    conn.GetStream().Write(data, 0, data.Length);
                    conn.GetStream().Flush();
                }
            }



客户端稍微简单一些,一个用于发送更改的线程,一个用于接收更新的线程.如果这里有问题,我相信它将在接收更新的同时-出于同样的原因,我认为服务器接收数据有误.



The client is a little simpler, one thread for sending changes, one thread for receiving updates. If there is an issue here, I believe it will be while receiving updates - for the same reasons I think the server receiving data is wrong.

//make initial contact with the server
            server = new TcpClient();
            IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(hostIP), hostPort); //127.0.0.1 //3000
            server.Connect(serverEndPoint);





//send changes to server
        private void sendUpdates() 
        {
            while (true)
            {
                lock (dataChanges)
                {
                    //Wait until there is data to send
                    while (dataChanges.Count == 0)
                        Monitor.Wait(dataChanges);

                    //if still connected to server
                    if (server.Connected)
                    {
                        NetworkStream nStream = server.GetStream();
                        nStream.Write(dataChanges.First.Value, 0, dataChanges.First.Value.Length);
                        nStream.Flush();

                        dataChanges.RemoveFirst();
                        Console.WriteLine("CLIENT: data change sent to server");
                    }
                    else Console.WriteLine("CLIENT: no longer connected to server");
                }
            }
        }

//recieve updates from server
        private void receiveUpdates() 
        {
            while(true)
            {
                //if still connected to server
                if (server.Connected)
                {
                    //Get data from stream
                    Console.WriteLine("CLIENT: waiting for data from server");
                    byte[] data = ReadToEnd(server.GetStream());

                    //Deserialize change
                    AbstractDataChange dChange = aData.deserialize(data);
                    Console.WriteLine("CLIENT: recieved data update from the server");

                    //update synched data
                    lock (aData)
                    {
                        aData.updateData(dChange);
                    }
                }
                else Console.WriteLine("CLIENT: no longer connected to server");
            }   
        }



.



.

推荐答案

如果是我,我将让客户端定期推送自己的更新并拉取其他客户端更新.这使得服务器不过是一个令人赞叹的数据交换所.它所做的只是侦听客户端连接,然后客户端驱动comm会话-而不是服务器.
If it were me, I would let the clients push their own updates and pull other client updates on a regular basis. That makes the server nothing more than a glorified data clearinghouse. All it does is listen for client connections, and then the clients drive the comm session - not the server.


好的,我的问题已经解决了.我删除了
Alright, my question has been solved. I removed the
ReadToEnd(conn.GetStream());


函数调用,并将其替换为


function call, and replaced it with

conn.GetStream().Read(data, 0, buffSize); 


我的客户端服务器运行正常,现在我只需要弄清楚如何发送任意长度的消息...

这是不要盲目复制粘贴!"的一个很好的例子.我使用的功能无法正常工作!


My client-server is functioning correctly, now I just need to figure out how to send messages of arbitrary length...

This is a good example of "Don''t blindly copy-paste!!" The function I used did not work as expected!


这篇关于实施C#客户端-服务器以保持游戏数据同步时出现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆