实施C#客户端-服务器以保持游戏数据同步时出现问题 [英] Problem implementing C# Client-Server to keep game data in sync
问题描述
我已经花了一段时间了(比预期的要长得多),但似乎仍然无法让客户端服务器使用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屋!