TcpConnection能够处理并发请求。客户端服务器

时间:2011-05-21 05:50:20

标签: c# concurrency tcp client-server

我正在尝试使用以下代码构建一个简单的客户端 - 服务器应用程序:

//SERVER
IPAddress ipAd = IPAddress.Parse("192.163.10.101");
TcpListener myList = new TcpListener(ipAd, 8001);
myList.Start();

Console.WriteLine("The server is running at port 8001...");
Console.WriteLine("The local End point is  :" + myList.LocalEndpoint);
Console.WriteLine("Waiting for a connection.....");

Socket s = myList.AcceptSocket();
Console.WriteLine("Connection accepted from " + s.RemoteEndPoint);

//CLIENT
TcpClient tcpclnt = new TcpClient();
Console.WriteLine("Connecting.....");
tcpclnt.Connect("192.163.10.101",8001); 
Console.WriteLine("Connected");

这实际上做了我需要的,其中客户端可以连接到服务器。但是,当我尝试运行客户端的多个实例以连接服务器时,服务器只接受第一个要连接的客户端。这意味着就像一对一的连接,其中只有一个客户端可以与客户端连接。但是,我需要的是让服务器能够接受来自多个客户端的连接。

如果有人能指出我可能的解决方案,我真的很感激!谢谢!

2 个答案:

答案 0 :(得分:1)

您需要再次调用AcceptSocket以接受另一个套接字 典型的设计是必须调用BeginAcceptSocket并在回调调用EndAcceptSocket中,将客户端处理调度到其自己的线程(或使用异步方法的工作线程),然后再次调用BeginAcceptSocket。

这个片段未经测试,但应该或多或少正确/让你思考正确的方向。

class Server
{
    public Server()
    {
        TcpListener listener = null;

        // init the listener

        listener.BeginAcceptSocket((ar) => AcceptLoop(ar, listener),null);
    }

    public void HandleClientSocketRead(IAsyncResult ar, byte[] recvBuffer, Socket clientSocket)
    {
        int recvd = clientSocket.EndReceive(ar);
        //do something with the data
        clientSocket.BeginReceive(recvBuffer, 0, 1024, SocketFlags.None, (ar2) => HandleClientSocketRead(ar2, recvBuffer, clientSocket), null);
    }

    public void AcceptLoop(IAsyncResult ar, TcpListener listener)
    {
        Socket clientSocket = listener.EndAcceptSocket(ar); // note that this can throw
        byte[] recvBuffer = new byte[1024];

        clientSocket.BeginReceive(recvBuffer, 0, 1024, SocketFlags.None, (ar2) => HandleClientSocketRead(ar2, recvBuffer, clientSocket), null);

        listener.BeginAcceptSocket((ar) => AcceptLoop(ar, listener), null);
    }
}

答案 1 :(得分:0)

如果您要编写服务器,一个好的设计是拥有[server] .exe和[client] .exe。 [server] .exe当然会接受并处理所有传入连接,维护客户端套接字,并执行您需要的任何操作。下面是一个非常基本示例,用于编写服务器以接受多个客户端套接字,并将它们存储在List对象中。但是,这不是多线程的,所以代码确实阻塞了。

<强> [服务器] .EXE

//-----------------------------------------------------------------------------
// <copyright file="Program.cs" company="DCOM Productions">
//     Copyright (c) DCOM Productions.  All rights reserved.
// </copyright>
//-----------------------------------------------------------------------------

namespace MultiSocketServerExample {
    using System;
    using System.Net.Sockets;
    using System.Net;
    using System.Collections.Generic;

    class Program {

        static List<Socket> m_ConnectedClients = new List<Socket>();

        static void Main(string[] args) {
            Socket host = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            host.Bind(new IPEndPoint(IPAddress.Any, 9999));
            host.Listen(1);

            while (true) {
                m_ConnectedClients.Add(host.Accept());
                Console.WriteLine("A client connected.");
            }
        }
    }
}

然后与您的客户合作:(再次,非常基本示例)

m_ConnectedClients[0].Send(Encoding.ASCII.GetBytes("hello!");

使用TcpListener和TcpClient,我认为使用Socket类进行网络编程要容易得多。我说这个的原因是它已经是一个非常好且易于使用的实现,并且通过使用TcpListener和TcpClient创建进一步的抽象,减少了你理解正在发生的事情的能力(在我看来)。