目录
TcpListener和TcpClient
在C#中实现TCP通信,你可以使用 System,Net.Sockets 命名空间中的 TcpListener 和
Tcpclient 类。
若要使用传输控制协议(TCP),有两个选项:使用 Socket以获得最大控制和性能,或使用 Icpclient 和IcpListener 帮助程序类。Icpclien 和 IcpListener 是在System.Net.Sockets.Socket 类的基础上建立的,并负责传输数据的详细信息以便于使用。
TcpListener和TcpClient的使用
连接到服务器
`TcpClient` 中的所有 `Connect`、`ConnectAsync`、`BeginConnect` 和 `EndConnect` 重载在功能上都等效于相应的 `Socket` 方法。
请考虑以下 TCP 客户端代码:
var client = new TcpClient();
client.Connect("www.example.com", 80);
上述 `TcpClient` 代码等效于以下套接字代码:
var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
socket.Connect("www.example.com", 80);
创建服务器套接字
就像与原始 `Socket` 对应项功能等效的 `TcpClient` 实例一样,本部分将 `TcpListener` 构造函数映射到其相应的套接字代码。 要考虑的第一个构造函数是 `TcpListener(IPAddress localaddr, int port)`。
var listener = new TcpListener(IPAddress.Loopback, 5000);
前面的 TCP 侦听器代码在功能上等效于下面的套接字代码:
var ep = new IPEndPoint(IPAddress.Loopback, 5000);
var socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
开始侦听服务器
Start()方法是组合 socket 的 Bind 和 Listen() 功能的包装器
var listener = new TcpListener(IPAddress.Loopback, 5000);
listener.Start(10);
前面的 TCP 侦听器代码在功能上等效于下面的套接字代码:
var endPoint = new IPEndPoint(IPAddress.Loopback, 5000);
var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(endPoint);
socket.Listen(10);
接收服务器连接
在后台,传入的TCP 连接在接受时始终会创建新的套接字。 TcpListener 可以直接接受 socket实例(通过 Acceptsocketl)或 AceptsocketAsymc),也可以接受 IcpClient(通过AcceptTcpClient()和AcceptTcpClientAsync())。
var listener = new TcpListener(IPAddress.Loopback, 5000);
var acceptedSocket = await listener.AcceptSocketAsync();
前面的 TCP 侦听器代码在功能上等效于下面的套接字代码:
var endPoint = new IPEndPoint(IPAddress.Loopback, 5000);
var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
var acceptedSocket = await socket.AcceptAsync();
创建 `NetworkStream` 以发送和接收数据
使用 Tcpclient 时,需要使用 Getstream()方法实例化NetworkStream,以便能够发送和接收数据。使用socket 时,必须手动创建 Networkstream
var client = new TcpClient();
NetworkStream stream = client.GetStream();
等效于以下套接字代码:
var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
var stream = new NetworkStream(socket, ownsSocket: true);
如果代码不需要使用 stream 实例,则可以直接依赖 scket 的发送/接收方法(Send、SendAsync、Receive和 ReceveAsync),而不是创建 Networkstream.
关闭连接
使用 `TcpClient` 时,需要使用 Close()方法关闭连接,
var client = new TcpClient();
client.Close();
使用TcpListener搭建Tcp服务器
TcpListener listener;
Dictionary<string, TcpClient> clientList = new Dictionary<string, TcpClient>();
private void button1_Click(object sender, EventArgs e)
{
// 按钮状态
openBtn.Enabled = false;
closeBtn.Enabled = true;
// 1.创建监听对象
listener = new TcpListener(IPAddress.Any, 3030);
// 2.开始监听(backlog:链接最大的挂起数)
listener.Start(100);
startListener(listener);
}
private void startListener(TcpListener lis)
{
// 3.等待链接(接收挂起的连接请求)
Task.Run(() =>
{
while (true)
{
try
{
TcpClient client = lis.AcceptTcpClient();
string ip = client.Client.RemoteEndPoint.ToString(); // 获取连接客户的IP
clientList.Add(ip, client);
startReceive(client.GetStream(), ip);
addRichTextBox($"{ip}已经连接到服务器");
}
catch (Exception ex)
{
lis.Stop();
break;
}
}
});
}
private void startReceive(NetworkStream stream, string ip)
{
Task.Run(() =>
{
while (true)
{
try
{
byte[] buffer = new byte[1024]; // 大小按情况而定
int length = stream.Read(buffer, 0, buffer.Length); // 返回本次接收数据的字节数
if (length == 0)
{
throw new Exception($"客户端{ip}断开连接");
}
else
{
string value = Encoding.Default.GetString(buffer, 0, length);
addRichTextBox($"接收到{ip}发送的消息:{value}\r\n");
}
}
catch
{
// 从字典中移除当前连接
clientList.Remove(ip);
addRichTextBox($"{ip}连接已断开\r\n");
break;
}
}
});
}
// 发送信息给客户端
private void sendBtn_Click(object sender, EventArgs e)
{
byte[] bytes = Encoding.Default.GetBytes(msgTextbox.Text);
// 循环所有的客户端发送数据(也可以根据IP选择给谁发送)
foreach (var item in clientList)
{
item.Value.GetStream().Write(bytes, 0, bytes.Length);
}
}
// 关闭按钮点击
private void closeBtn_Click(object sender, EventArgs e)
{
// 控制按钮状态
closeBtn.Enabled = false;
openBtn.Enabled = true;
foreach (var item in clientList)
{
TcpClient client = item.Value;
client.Close();
}
listener.Stop();
}
private void addRichTextBox(string text)
{
richTextBox1.Invoke(new Action(() =>
{
richTextBox1.AppendText(text);
// 让rich滚动到最下面
richTextBox1.SelectionStart = richTextBox1.Text.Length;
richTextBox1.ScrollToCaret();
}));
}
TcpClient用于客户端和服务器连接
简单代码示例如下
private TcpClient tcpClient;
private void button1_Click(object sender, EventArgs e)
{
// 1.创建客户端对象
tcpClient = new TcpClient();
// 2.开始链接
tcpClient.Connect(IPAddress.Parse("127.0.0.1"),3030);
// 3.获取数据流 Stream(读read 和 写write)
NetworkStream stream = tcpClient.GetStream();
// 4. 开启分线程
Thread thread = new Thread(ClientThread);
thread.Start(stream);
}
// 开分线程,收发消息
private void ClientThread(object obj)
{
NetworkStream stream = obj as NetworkStream;
while (true)
{
// 5.向服务器发送消息(自定义一个带输入框的对话框)
string info = "张三发送的消息";
byte[] bytes = Encoding.UTF8.GetBytes(info);
stream.Write(bytes,0,bytes.Length);
// 6.接收来自服务器的消息
byte[] buffer = new byte[1024];
int length = stream.Read(buffer,0,buffer.Length);
string msg = Encoding.UTF8.GetString(buffer,0,length);
MessageBox.Show(msg);
}
}
本篇文章部分参考于网络,如有侵权请联系本人删除!!!