故事
我正在尝试编写一个开源RPG库存服务器,可以同时使用一个以上的RPG,并且稍后会为它制作一个游戏。我的第一个版本不支持很多安全性或加密。但我想有一个良好的开端。
问题
它接受一个连接,掉线。但我的线程实现似乎只接受一个连接。有人可以给我一个如何正确做到这一点的指导方针吗?我已经评论了我将为您的阅读提供的代码。
设置 我使用启用了SP1的visual studio 2010。我只在家庭网络中尝试过,因此不需要IP转发。它同时接受两台PC。
非常感谢帮助的人,如果你有所帮助,并希望在最终结果中得到记录,请告诉我。如果有人有一般性评论,我很乐意听到他们的意见;)
编辑:它与NewIPEP()方法有关。
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace TCPServer1
{
class ServerV1
{
static int maxthreads = 4;
static bool[] threadavailable = new bool[maxthreads];
static Thread[] listenThread = new Thread[maxthreads];
static IPEndPoint[] ipep = new IPEndPoint[maxthreads];
static bool[] threadconnected = new bool[maxthreads];
static Socket[] newsock = new Socket[maxthreads];
static Socket[] client = new Socket[maxthreads];
static ItemListClassV1 parent;
static Login loginin;
static ProtoColV1[] protocol = new ProtoColV1[maxthreads];
/// <summary>
/// initialises variables and starts a first thread.
/// </summary>
/// <param name="args"></param>
public ServerV1(ItemListClassV1 parentid, Login login)
{
for (int i = 0; i < maxthreads; i++)
{
threadavailable[i] = true;
}
parent = parentid;
loginin = login;
StartThread();
}
/// <summary>
/// should be split but handles the servershit look further for seperate "method" comments
/// </summary>
static void Server()
{
int recv = 0;
byte[] data = new byte[1024];
//looks for incoming connections
ipep[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)] = NewIPEP();
newsock[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)] = new
Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
newsock[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Bind(ipep[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)]);
newsock[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Listen(10);
Console.WriteLine("Waiting for a client...");
client[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)] = newsock[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Accept();
//if connected
IPEndPoint clientep =
(IPEndPoint)client[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].RemoteEndPoint;
Console.WriteLine("Connected with {0} at port {1}",
clientep.Address, clientep.Port);
//if connection start a new thread
StartThread();
//send welcome message to client
string welcome = "Welcome to my test server";
data = Encoding.ASCII.GetBytes(welcome);
client[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Send(data, data.Length,
SocketFlags.None);
while (true)//this looks for incoming data and sends reply.
{
try
{
data = new byte[1024];
recv = client[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Receive(data);
}
catch (SocketException e)
{
if (e != null)
break;
}
if (client[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Connected != true)//when not connected break the loop
{
break;
}
////EXECUTES moet wer trug
//byte[][] packets = protocol[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Execute(data,recv);//EXECUTES THE DATA EXTERNALLY
byte[][] packets = new byte[1][];
packets[0] = data;
for (int i = 0; i < packets.Length; i++)//stuurt vervolgens alle pakketjes
{
client[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Send(packets[i], packets[i].Length,
SocketFlags.None);
}
}
//when not connected this continues
Console.WriteLine("Disconnected from {0}",
clientep.Address);
//close socket
client[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Close();
newsock[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)].Close();
bool full = true;
//if the server was full now a slot opened
for (int l = 0; l < maxthreads; l++)
{
if (threadavailable[l])
{
full = false;
}
if (!threadavailable[l] && !threadconnected[l])
{
full = false;
}
}
//closes thread, deletes information
threadavailable[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)] = true;
ipep[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)] = null;
protocol[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)] = null;
if (full)
{
StartThread();
}
//stops thread
listenThread[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)] = null;
System.Threading.Thread.CurrentThread.Abort();
}
/// <summary>
/// keeps searching for incoming connections and returns the found connection when found.
/// </summary>
/// <returns></returns>
static IPEndPoint NewIPEP()
{
IPEndPoint temp = null;
bool newconnection = false;
while (!newconnection)
{
temp = new IPEndPoint(IPAddress.Any, 9050);
for (int k = 0; k < maxthreads; k++)
{
if (!threadavailable[k] && ipep[k] != null && ipep[k].Address != null )
{
if (temp.Address == ipep[k].Address)
{
k = maxthreads;
break;
}
}
if (k == maxthreads - 1)
{
newconnection = true;
threadconnected[Convert.ToInt32(System.Threading.Thread.CurrentThread.Name)] = true;
}
}
}
return temp;
}
/// <summary>
/// finds the first unstarted thread and starts it
/// </summary>
static void StartThread()
{
for (int i = 0; i < maxthreads; i++)
{
if (threadavailable[i])
{
threadavailable[i] = false;
threadconnected[i] = false;
protocol[i] = new ProtoColV1(parent,loginin);
listenThread[i] = new Thread(Server);
listenThread[i].Name = Convert.ToString(i);
listenThread[i].Start();
break;
}
}
}
}
}
答案 0 :(得分:1)
您只调用了Socket client = newsock.Accept();
一次,这就是为什么只接受一个客户端的原因。
答案 1 :(得分:1)
这不是答案,但我不知道如何添加评论......你有没有检查过Lidgren?为什么重新发明轮子? http://code.google.com/p/lidgren-network-gen3/
他有关如何使用该库的相同的很好的例子。
祝你好运!Linuxx