C#.Net套接字服务器客户端

时间:2015-06-22 09:53:05

标签: c# .net sockets tcp

我对C#中的.Net套接字有点问题。 我编写了一个客户端和一个使用TCP的服务器。

当客户端打开时,它会向服务器发送握手。服务器回答它的状态(客户,客户接受,......)。之后,应用程序发送getdata-request,放弃连接并侦听服务器的响应'。现在,服务器构建与客户端的连接,并发送客户端所需的所有数据。

代码和其他一切正常,但问题是:

在我们公司的testserver上工作正常,在实时服务器上只有握手才能工作。在它之后,客户端不再接收任何数据。两个服务器上的服务应用程序是相同的。

我认为问题是由某些防火墙造成的(服务器想要建立到客户端的tcp连接 - >不好),但是系统管理员说没有防火墙可以阻止它。

现在,我正在寻找一种不会花费太多时间和代码更改的(廉价的)解决方案。如果有人知道如何在理论上解决这个问题,那就太好了。

BTW:除了运行serverapplication之外,我不允许在实时服务器上做任何事情。我无法在此服务器上进行调试。

我无法发布我的所有代码,但如果您需要查看其中的特定部分,请提出要求。

--- --- EDIT

客户端 - 服务器通信

1)客户启动
   客户端发送握手(新的TCP连接)
2)服务器验证握手并保存IP
   服务器响应它的客户端状态(相同的tcp连接)
3)客户确认此响应并放弃此连接
   客户端发送getdata-request(新的tcp连接)
   客户端也放弃了这个tcp连接 4)服务器接收getdata-request并在主数据库中收集所需数据    服务器将所有收集的数据发送到客户端(多个tcp连接)
5)客户端接收所有数据并将其显示在其GUI中(多个tcp连接以及通过使用AutoResetEvents和Counts of socket发送来保存数据的顺序)

这是我的代码所做的主要部分。它到目前为止还不是最好的,但我猜的就是我写的。第一步,第二步和第三步按预期工作。数据的处理也很好。 我忘了提到的另一件事是该解决方案使用两个端口' 16777'和' 16778'。一个接收/收听和一个发送。 我的代码基于异步serverclient的MSDN示例。

发送握手(和getdata-request)

    public void BeginSend(String data)
    {
        try
        {
            StateObject state = new StateObject();
            state.workSocket = sender;

            byte[] byteData = Encoding.UTF8.GetBytes(data);

            sender.BeginSend(byteData, 0, byteData.Length, 0,
                new AsyncCallback((IAsyncResult e) =>
                {
                    Socket socket = (Socket)e.AsyncState;
                    SocketBase.StateObject stateObject = new SocketBase.StateObject();
                    stateObject.workSocket = socket;
                    socket.BeginReceive(stateObject.buffer, 0, 256, SocketFlags.None, new AsyncCallback(this.ReadCallback), (object)stateObject);

                }), sender);

            sender = RetrieveSocket(); //Socketreset

            Thread.Sleep(100);
        }
        catch /*(Exception e)*/
        {
            //--
        }
    }

服务器侦听器

    public void StartListening()
    {
        listener = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp);

        // Bind the socket to the local endpoint and listen for incoming connections.
        try
        {
            listener.Bind(localEndPoint);
            listener.Listen(System.Int32.MaxValue);

            while (true)
            {
                // Set the event to nonsignaled state.
                allDone.Reset();

                // Start an asynchronous socket to listen for connections.
                listener.BeginAccept(
                    new AsyncCallback(AcceptCallback),
                    listener);

                // Wait until a connection is made before continuing.
                allDone.WaitOne();
            }

        }
        catch (Exception e)
        {
             //--
        }
    }

    public void AcceptCallback(...);
    public void ReadCallback(...);

套接字发送

    private void Send(Socket handler, String data)
    {
        Socket t = RetrieveSocket(((IPEndPoint)handler.RemoteEndPoint).Address);
        // Convert the string data to byte data using ASCII encoding.
        byte[] byteData = Encoding.UTF8.GetBytes(data);

        // Begin sending the data to the remote device.
        t.BeginSend(byteData, 0, byteData.Length, 0,
            new AsyncCallback(SendCallback), t);
    }

套接字发送所有数据部分(回答getdata-request | socToHandle应该是getdata-request先前连接的套接字)

    private void SendAllData(Socket socToHandle, string PakContent)
    {
        #region IsThereADatetime? //Resolve a given datetime

        #region GiveClientNumberOfPackets //Send the client info about how much he has to receive (See line below)

            Send(socToHandle, "ALERT#TASKCOUNT;OPT-" + GetBestDate(dateStart) + EndSocket); 


        #region #SendResouces
        #region #SendGroups
        #region #SendTasks
    }

查看我的旧代码,我有一个想法=>

我可以通过更改以下内容通过同一连接发送所有内容:

Socket t = RetrieveSocket(((IPEndPoint)handler.RemoteEndPoint).Address);

(创建新连接)到使用相同连接的东西? 如果这样可行,我该怎么做? 并且客户端的侦听器部分是否仍然会收到单个数据包?

1 个答案:

答案 0 :(得分:1)

服务器及其环境配置为正确处理传入请求。客户端通常位于路由器后面,默认情况下,它们无法接收来自网络外部的传入连接(这是一件好事)。

要启用传入连接,您可以将路由器配置为将特定端口号的所有请求转发到您的计算机。但是,您的网络上没有其他人能够运行客户端。

这就是为什么在典型的多客户端 - 单服务器环境中,客户端进行所有连接,只有服务器需要对网络环境进行任何更改。

我不知道为什么你选择从服务器端连接到客户端,但我强烈建议不要这样做 - 任何使用这种机制的廉价解决方案最终可能会变得非常昂贵。