c#网络编程中tcpListener和tcpClient的用法

谁能给个具体的例子?... 谁能给个具体的例子? 展开
 我来答
xuesongsh
推荐于2018-03-22
知道答主
回答量:1
采纳率:0%
帮助的人:1699
展开全部
在本教程中,我会向你展示如何用C#建立一个线程中的TCP服务端。如果你用过windows的sockets编写程序,你就知道有多麻烦。感谢.net框架,使得网络编程变得更容易了。

我们将建立一个非常简单的的服务器接受客户端连接,并可以发送和接收数据。服务器为每一个连接客户端产生一个线程,从理论上讲,可以接受多个连接(虽在实践中,Windows对此是有限制)。
下面看代码:

using System;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;

namespace TCPServerTutorial
{
class Server
{
private TcpListener tcpListener;
private Thread listenThread;

public Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, 3000);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
}
}

上面建立了一个基本的服务器类。我们定义了一个TcpListener变量(TcpListener封装了底层套接字通信工作),同时定义了一个线程用于监听客户端的连接。接下来我们定义了ThreadStart的委托函数:ListenForClients。
代码如下:

private void ListenForClients()
{
this.tcpListener.Start();

while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();

//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}

这个函数非常简单。首先,它启动TcpListener,然后循环接受连接。 AcceptTcpClient的调用将阻塞线程的执行,直到一个客户端连接,在这里,我们触发一个线程来处理与我们的新客户端的通信。我用了ParameterizedThreadStart委托,所以我可以传递AcceptTcpClient调用返回的TcpClient对象到新线程。

ParameterizedThreadStart使用函数HandleClientComm。这个函数负责从客户端读取数据。让我们看看它。

private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();

byte[] message = new byte[4096];
int bytesRead;

while (true)
{
bytesRead = 0;

try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
//a socket error has occured
break;
}

if (bytesRead == 0)
{
//the client has disconnected from the server
break;
}

//message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
System.Diagnostics.Debug.WriteLine(encoder.GetString(message, 0, bytesRead));
}

tcpClient.Close();
}

第一步将client类型转换为TcpClient类型,因为ParameterizedThreadStart委托只能接受基本对象类型。下一步,从TcpClient得到NetworkStream用来读取数据。之后,通过一个while循环从客户端读取数据。 read调用会一直处于阻塞状态,直到从客户端接收到数据。如果从客户端读取到零字节,那么说明客户端已断开。在该例子里,我只是一个字符串转换成字节数组,并将它输出到控制台。当然,你会做一些更复杂的工作。如果socket出现错误或客户端断开连接,你应该调用TcpClient对象的close函数关闭连接,释放它使用的任何资源。

上面就是创建一个服务器线程,接受连接,并从客户端读取数据所需做的所有的事情。当然,如果服务端不能发送数据,那么就没什么用了。下面,让我们看看如何将数据发送到我们的连接的一个客户端。

NetworkStream clientStream = tcpClient.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Client!");

clientStream.Write(buffer, 0 , buffer.Length);
clientStream.Flush();

从AcceptTcpClient返回的TcpClient对象用来发送数据给客户端。因此需要在服务端保存这些对象。通常可以创建一个TcpClient对象的集合。发送数据是非常简单的,只需要得到client的NetworkStream对象,然后调用它的write方法就可以了。

TCP服务端已经完成了。比较难的部分是定义一个协议用来在客户端和服务端之间发送信息。应用层的协议通常对不同的应用都是不一样的。所以我不打算讲解更多,你只需要实现你自己的。

如果没有一个客户端连接到服务端,那么这个服务端还有存在的意思吗?本教程主要是讲服务端编程,但这里有一个简短的代码,说明了如何设置一个基本的TCP连接,并发送一段数据。

TcpClient client = new TcpClient();

IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000);

client.Connect(serverEndPoint);

NetworkStream clientStream = client.GetStream();

ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Server!");

clientStream.Write(buffer, 0 , buffer.Length);
clientStream.Flush();

第一步工作是获取客户端到服务端的连接。使用TcpClient.Connect方法。它需要知道服务端的IPEndPoint,在这里,我将连接到本地主机,端口号3000。然后发送字符串"hello Server!"

注意:从客户端或服务器写并不总是等于一个在接收端读。例如,客户端向服务器发送10个字节,但服务器可能无法在第一次读取的时候得到所有10个字节。使用TCP,几乎保证最终得到所有10个字节,但它可能需要不止读取一次。所以当设计交互协议的时候要注意这一点。

参考资料: http://ilewen.com/questions/514

day忘不掉的痛
推荐于2016-05-15 · 知道合伙人数码行家
day忘不掉的痛
知道合伙人数码行家
采纳数:62646 获赞数:223928
本人担任公司网络部总经理多年,有充足的网络经验、互联网相关知识和资讯。

向TA提问 私信TA
展开全部
TCPListener类用于监听客户端连接请求。
TCPClient类用于提供本地主机和远程主机的连接信息。
两个类都位于 System.Net.Socckets命名空间下
方法 说明
AcceptSocket 从端口处接收一个连接并赋予它Socket对象
AcceptTcpClient 从端口处接收一个连接并赋予它TCPClient对象
Equals 判断两个TcpListener对象是否相等
GetType 获取当前实例的类型
Pending 确定是否有挂起的连接请求
Start 开始接听传入的连接请求
Stop 关闭监听器
ToString 创建TcpListener对象的字符串表示
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
七终多E
2011-08-25 · TA获得超过1.4万个赞
知道大有可为答主
回答量:3756
采纳率:46%
帮助的人:3382万
展开全部
留下邮箱 我有 (服务端未加try catch捕捉错误 所以在客户端退出时会报错 但是不影响通讯使用)
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 1条折叠回答
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式