在C#中,实现了很多对Windows API的封装,在套接字通信方面也是如此。下面是一个TCP网络通信的简单实例,因为自己初学C#,记下来学习
使用名字空间:
using System.Net;
using System.Net.Sockets;
服务器端:
五个步骤:
(1) 创建一个TcpListener类的对象,也叫“侦听器”,通过它,服务器能监听到客户的请求。
下面是TcpListener构造函数的3种实现:
TcpListener(Int32) 在指定端口号进行监听,现在比较少用
TcpListener(IPEndPoint) 绑定端点(包括IP和端口号)
TcpListener(IPAddress, Int32) 绑定IP和端口号
IPAddress类有一个方法Parse(),可以将IP 地址字符串转换为IPAddress 实例。
TcpListener类封装了套接字的创建(socket)和绑定(bind),简化了编程的输入
(2) 调用TcpListener类的Start()方法。该方法可以使TcpListenerduixiang开始监听连接请求。
(3) 方法AcceptSock()可以接收来自客户端的连接请求。该方法返回一个Socket类的对象,该对象是实现与客户端通信的套接字;
(4) 调用Sockets类的Receive和Send方法来通信;
(5) 使用Socket对象的Close()方法关闭连接;
使用TcpListener类的Stop()方法关闭侦听器。
客户端:
五个步骤:
(1) 创建一个TcpClient类的对象
TcpClient() 初始化 TcpClient 类的新实例。
TcpClient(AddressFamily) 使用指定的族初始化 TcpClient 类的新实例。
TcpClient(IPEndPoint) 初始化 TcpClient 类的新实例,并将其绑定到指定的本地终结点。
TcpClient(String, Int32) 初始化 TcpClient 类的新实例并连接到指定主机上的指定端口。
(2) 使用TcpClient类的Connect方法建立与服务器的连接。
疑惑:这里的Connect方法同样可以实现与指定IP和端口的服务器连接,那TcpClient类的构建函数中就没必要指定IP和端口了
(实际上,在下面的例子中,创建TcpClient对象时,并没有传参数)
(3) 使用TcpClient的GetStream()方法来得到一个用于发送和接收数据的NetworkStream对象。
NetworkStream的WriteByte和Write方法分别能够用于向服务器输出单字节或一组字节;ReadByte和Read方法分别能从服务器读取单字节或一组字节;
public override void Write( byte[] buffer, int offset, int size )
参数解析:
buffer:类型 Byte 的数组,该数组包含要写入 NetworkStream 的数据。
offset:buffer 中开始写入数据的位置,一般取0;
size:要写入 NetworkStream 的字节数,取值为buffer.Length-offset。
(当offset=0时,size=buffer.Length)
Read()方法类似,不单做解释;
(4) 使用NetworkStream对象的WriteByte,Write,ReadByte,Read方法与服务器进行通信;
(5) 调用NetworkStream的Close方法来关闭连接;接着调用TcpClient类的Close()方法来终止TCP连接。
注意事项:
无论是Socket类的Receive()或Send()方法,还是NetworkStream的Read()或Write()方法,都是直接读写Byte[]类型的变量,而我们习惯使用string类型的变量
使用如下转换:
字节数组到字符串:
Encoding.ASCII.GetString()
public virtual string GetString( byte[] bytes )
输入byte[]类型变量,输出string类型变量;
字符串到字节数组:
Encoding.ASCII.GetBytes()
public virtual byte[] GetBytes( string s )
输入string类型变量,输出byte[]类型变量;
代码实现:
实现功能:客户端向服务器发送信息,服务器在控制台显示接收到的信息;
服务器端:
namespace tcplistenerTest
{
class Program
{
static void Main(string[] args)
{
string srvIP = "127.0.0.1";
IPAddress srvAddr = IPAddress.Parse(srvIP);
int nPort = 2030;
//创建并绑定套接字
TcpListener srvLstner = new TcpListener(srvAddr, nPort);
//开始监听
try
{
srvLstner.Start(5);
}
catch (SocketException e)
{
Console.WriteLine(e.Message);
srvLstner.Stop();
Console.ReadLine();
return;
}
//接受客户端连接请求
while (true)
{
//接收连接请求
Socket remoteSock = srvLstner.AcceptSocket();
//显示客户端发送过来的消息
Byte[] recvBuf = new Byte[128];
try
{
remoteSock.Receive(recvBuf);
}
catch (SocketException e)
{
Console.WriteLine(e.Message);
break;
}
string recvMsg = Encoding.ASCII.GetString(recvBuf);
Console.WriteLine(recvMsg);
remoteSock.Close();
}
srvLstner.Stop();
}
}
}
客户端:
namespace TcpClientTest
{
class Program
{
static void Main(string[] args)
{
TcpClient tcpClient = new TcpClient();
IPAddress srvAddr = IPAddress.Parse("127.0.0.1");
int nPort = 2030;
//连接到服务器
try
{
tcpClient.Connect(srvAddr, nPort);
}
catch (SocketException e)
{
Console.WriteLine(e.Message);
tcpClient.Close();
Console.ReadLine();
return;
}
NetworkStream sockStream = tcpClient.GetStream();
string sendMsg = "hello, srver! This is client A";
Byte[] sendBuf = Encoding.ASCII.GetBytes(sendMsg);
try
{
sockStream.Write(sendBuf, 0, sendBuf.Length);
}
catch (SocketException e)
{
Console.WriteLine(e.Message);
sockStream.Close();
tcpClient.Close();
Console.ReadLine();
return;
}
Console.WriteLine("成功向服务器发送消息:{0}\n", sendMsg);
sockStream.Close();
tcpClient.Close();
Console.ReadLine();
}
}
}