为什么这个多线程多连接TCP服务器只接受一个连接?

时间:2013-05-26 01:13:15

标签: c# .net multithreading tcp

所有这些背后的

故事

我正在尝试编写一个开源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;

            }
        }
    }





}
}

2 个答案:

答案 0 :(得分:1)

您只调用了Socket client = newsock.Accept();一次,这就是为什么只接受一个客户端的原因。

答案 1 :(得分:1)

这不是答案,但我不知道如何添加评论......你有没有检查过Lidgren?为什么重新发明轮子? http://code.google.com/p/lidgren-network-gen3/

他有关如何使用该库的相同的很好的例子。

祝你好运!

Linuxx