【C#食谱】【杭帮菜】菜单1:写一个TCP服务端

问题:

你需要写一个服务端去监听从某一个端口进来的一个TCP客户端的请求。然后,这些请求可以在服务端被处理,并且每一个响应都可以被发送到TCP客户端。我将在下一个“菜”中介绍怎么样创建一个TCP客户端和服务端进行交互。

解决方法:

我们创建一个MyTcpServer的类来监听从一个端口进来的基于TCP终端的请求:


class  MyTcpServer
{
    Private Membersregion Private Members

private TcpListener _listener = null;

private IPAddress _address;

private int _port;

private bool _listening = false;

#endregion


    构造函数#region 构造函数

    
public MyTcpServer(IPAddress address, int port)

{

_port 
= port;

_address 
= address;

}


#endregion
 // 构造函数
}

这个MyTCPServer类有两个属性:

  • Address(IPAddress)
  • Port(int)

下面这些返回当前服务端正在监听的地址和端口,并且返回监听的状态:

属性 #region 属性

public IPAddress Address
{
    
get return _address; }
}


public int Port
{
    
get return _port; }
}


public bool Listening
{
    
get return _listening; }
}


#endregion

这个Listen方法告诉MyTcpServer类开始在某个地址和端口对上开始监听。你创建并启动了一个TcpListener,然后调用它的AcceptTcpClient方法去等待一个客户端请求的到来。一旦客户端连接成功,一个请求将被发送到线程池去处理客户端,它将运行ProcessClient方法。

监听器将在处理完客户端的请求后关闭:

public   void  Listen()
{
    try
    {
        lock (_syncRoot)
        {
            _listener 
= new TcpListener(_address, _port);
            // 启动服务器
            _listener.Start();

            // 设置为监听状态
            _listening = true;
        }


        // 监听
        do
        {
            Trace.Write(
"Looking for someone to talk to…?");

            // 等待连接
            TcpClient newClient = _listener.AcceptTcpClient();
              Trace.WriteLine(
"Connected to new client");

            // 排队处理客户的请求
            ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessClient), newClient);
        }
while (_listening);
    }

    catch (SocketException se)
    {
        Trace.WriteLine(
"SocketException: " + se.ToString()); 
    }
 
    finally 
    {
        // 关闭
        StopListening();
    }

}
StopListening方法使得TCPServer停止监听请求:
public   void  StopListening()
{
    if (_listening)
    {
        lock (_syncRoot)
      
{
            // 设置为非监听状态
            _listening = false;
            // 关闭
            _listener.Stop();
        }

    }

}
 
 

ProcessClient方法在一个线程池上被执行用来处理一个已经连接的客户端。它通过TcpClient.GetStream方法从客户端得到NetworkStream,然后读取整个请求。在返回一个响应后,它关闭客户端的连接。

私有方法 #region 私有方法
        
private void ProcessClient(object client)
        
{
            TcpClient newClient 
= (TcpClient)client;
            
try
            
{
                
// 缓存读取的数据
                byte[] bytes = new byte[1024];
                StringBuilder clientData 
= new StringBuilder();

                
// 获取NetworkStream
                using (NetworkStream ns = newClient.GetStream())
                
{
                    
// 初始化一个连接的read timeout为1分钟
                    ns.ReadTimeout = 60000;
                    
int bytesRead = 0;
                    
do
                    
{
                        
// 读取数据
                        try
                        
{
                            bytesRead 
= ns.Read(bytes, 0, bytes.Length);
                            
if (bytesRead > 0)
                            
{
                                
// 把bytes数据转换成ASCII类型的字符串,并加到末尾 
                                clientData.Append(
                                Encoding.ASCII.GetString(bytes, 
0, bytesRead));
                                
// 减少read timeout到1秒
                                ns.ReadTimeout = 1000;
                            }

                        }

                        
catch (IOException ioe)
                        
{
                            
// 读取超时;所有的数据都已经被读取了
                            Trace.WriteLine("Read timed out: " + ioe.ToString());
                            bytesRead 
= 0;
                        }

                    }

                    
while (bytesRead > 0);

                    Trace.WriteLine(
"Client says: " + clientData.ToString());

                    bytes 
= Encoding.ASCII.GetBytes("Thanks call again!");

                    
// 返回一个响应
                    ns.Write(bytes, 0, bytes.Length);
                }

            }

            
finally
            
{
                
// 关闭客户端的连接
                if (newClient != null)
                    newClient.Close();
            }

        }

        
#endregion
一个简单的监听客户端的服务端程序是这样的:
         class  Program
        
{
            
static MyTcpServer server = null;

            
static void Main(string[] args)
            
{
                
// 在另一个线程上运行服务端
                ThreadPool.QueueUserWorkItem(RunServer);
                Console.WriteLine(
"Press Esc to stop the server…?");
                ConsoleKeyInfo cki;
                
while (true)
                
{
                    cki 
= Console.ReadKey();
                    
if (cki.Key == ConsoleKey.Escape)
                        
break;
                }

            }


            
static void RunServer(object stateInfo)
            
{
                
// 启动
                server = new MyTcpServer(IPAddress.Loopback, 55555);
                server.Listen();
            }

        }


 
 
 
 
MyTcpServer类使用传进来的IP地址和端口号作为参数,并且在Listen方法中在该IP地址和端口上创建一个TcpListener。
一旦创建成功,TcpListener.Start方法被调用来启动服务器。个阻塞的AcceptTcpClient方法被调用来监听来自基于TCP的客户端的请求。一旦建立连接,ProcessClient方法将执行。
在这个方法中,服务器从客户端读取数据,并返回一个可信的响应。服务器通过NetworkStream.Close方法和TcpClient.Close方法来中断和客户端的连接。
StopListening方法被调用的时候,服务器停止监听。StopListening方法通过调用TcpListener.Stop方法来使服务器掉线。
写一个TCP客户端

转载于:https://www.cnblogs.com/adaiye/archive/2008/04/21/TCPServer.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值