简体   繁体   中英

C# .Net Socket Server Client

I've got a little problem with the .Net Sockets in C#. I programmed a client and a server working with TCP.

As the client is opened it sends a handshake to the server. The server answers with it's state (clientexists, clientaccepted,...). After that the application sends a getdata-request, abandons the connection and listens for the server's 'response'. Now, the server builds a connection to the client and sends all the data the client needs.

The code and everything else works, but the problem:

On our company testserver it works fine, on the live server only the handshake works. After it the client doesn't receive any more data. Serverapplication is the same on both servers.

I thought the problem was caused by some firewall (server wants to build a tcp connection to the client -> not good), but the system administrator said there is no firewall that could block that.

Now I'm searching for a ('cheap') solution that doesn't take too much time and changes in code. If anyone knows how to theoretically solve that, that would be great.

BTW: I am not allowed to do anything on the live server other than run the serverapplication. I don't have the possibility to debug on this server.

I can't publish all of my code, but if you need to see specific parts of it, ask for it please.

---EDIT---

Client-Server communication

1) Client startup
Client send handshake (new tcp connection)
2) Server validates handshake and saves IP
Server responds with it's client state (same tcp connection)
3) Client acknowledges this response and abandons this connection
Client sends getdata-request (new tcp connection)
Client abandons this tcp connection, too
4) Server receives getdata-request and collects the needed data in the main database
Server sends all the collected data to the client (multiple tcp connections)
5) Client receives all data and displays it in it's GUI (multiple tcp connections and the order of the data is kept by working with AutoResetEvents and Counts of sockets to send)

This is the main part my code does. It's by far not the best but it was for me as I wrote it I guess. Step one, two and three work as intended. The processing of the data works fine, too. Another thing i forgot to mention is that the solution uses two Ports '16777' and '16778'. One to receive/listen and one to send. My code is based on the MSDN example of the asynchronous server and client .

Sending a handshake (and 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)*/
        {
            //--
        }
    }

Server listener

    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(...);

Socket send

    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);
    }

Socket send all data part (answer to getdata-request | socToHandle should be the socket of the previous connection of the 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
    }

Looking through my old code I have one idea =>

Could I send everything over the same connection by changing:

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

(which creates a new connection) to something that uses the same connection? If that would work, how can I do that? And would the listener part of the client still receive single packets?

Servers and their environment are configured to handle incoming requests properly. Clients are usually behind a router, which by default make them unable to receive incoming connections from outside their network (a good thing).

To enable incoming connections, you could configure your router to forward all requests for a certain port number to your machine. No one else on your network would be able to run the client then, though.

This is why in a typical multiple clients-single server environment, the client makes all the connections, and only the server requires any changes to the network landscape.

I don't know why you chose to connect to the clients from the server side, but I would strongly advise against this - any cheap solution that uses this mechanism may turn out to be very expensive in the end.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM