c#发展

注册

 

发新话题 回复该主题

TcpSocket入门初体验Echo [复制链接]

1#

《简述网络编程中的socket》阐述了socket的基本概念,从这一篇的Echo开始逐步打造一个完整的网络应用程序。

Echo是一个简单的回显程序,客户端向服务端发送消息,然后服务端将该消息完整地返回,我们在这里基于TCP协议实现该程序,代码如下:

服务端代码:

usingSystem;

usingSystem.Linq;

usingSystem.Net;

usingSystem.Net.Sockets;

usingSystem.Text;

namespaceEcho.Server

{

publicclassTcpServer

{

publicvoidStart(intport)

{

//创建服务端的Socket

m_socketServer=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

//创建IP和端口节点对象

IPEndPointendPoint=newIPEndPoint(IPAddress.Any,port);

//为监听socket绑定IP和端口

m_socketServer.Bind(endPoint);

//把监听socket至于被动监听状态

m_socketServer.Listen(10);

//accept函数会在此处阻塞,直到有客户端的连接请求,根据该请求的创建新的socket

Console.WriteLine("开始监听,等待客户端连接...");

SocketclientSocket=m_socketServer.Accept();

Console.WriteLine("客户端已连接,开始接收数据...");

while(true)

{

//初始化一个用于接收数据的字节数组

byte[]buf=newbyte[];

//receive会阻塞程序,直到接收到数据

intrcvLen=clientSocket.Receive(buf);

stringmsg=Encoding.UTF8.GetString(buf.Take(rcvLen).ToArray());

Console.WriteLine($"来自客户端的数据:{msg}");

clientSocket.Send(buf.Take(rcvLen).ToArray());

}

}

privateSocketm_socketServer;

}

}

main函数调用代码:

staticvoidMain(string[]args)

{

TcpServerserver=newTcpServer();

server.Start();

}

客户端代码:

usingSystem;

usingSystem.Linq;

usingSystem.Net;

usingSystem.Net.Sockets;

usingSystem.Text;

namespaceEcho.Client

{

publicclassTcpClient

{

publicSocketConnect(stringip,intport)

{

Sockets=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

IPEndPointendPoint=newIPEndPoint(IPAddress.Parse(ip),port);

s.Connect(endPoint);

returns;

}

publicvoidInputLoop(Sockets)

{

while(true)

{

Console.Write("等待输入:");

stringmsg=Console.ReadLine();

byte[]buf=Encoding.UTF8.GetBytes(msg);

s.Send(buf);

byte[]bufServer=newbyte[];

intrcvlen=s.Receive(bufServer);

Console.WriteLine($"接收到服务端的回写:{Encoding.UTF8.GetString(bufServer.Take(rcvlen).ToArray())}");

}

}

}

}

main函数调用代码:

staticvoidMain(string[]args)

{

TcpClientclient=newTcpClient();

Console.Write("按任意键发起连接请求");

Console.ReadKey();

Sockets=client.Connect(".0.0.1",);

Console.WriteLine("成功连接到服务端");

client.InputLoop(s);

}

为了模拟服务端和客户端两个进程,分别创建了两个C#的控制台项目,Echo.Server和Echo.Client,这两个程序都在本机进行调试,具体的工作过程如下:

服务端会创建监听套接字,该套接字绑定的终结点IP地址为--IPAddress.Any,该值表示服务端会接受本机任何IP地址收到的请求;端口可以在合法值范围内任选一个,笔者选取的是,在同一台设备上,端口不能重用,如果出现端口重用的问题,可以换一个可用端口再次尝试。

接下来是打开被动监听,即代码中的对Listen函数的调用,其中参数值的选取不属于本篇范围,后续章节会展开说明。再往后的Accept函数会阻塞主线程,等待客户端连入,该函数结束阻塞后返回新的Socket对象,利用这个新的Socket对象可以在服务端和客户端两个端点间进行数据交互。

新的Socket对象调用接收函数Receive向系统发起IO请求,等待客户端数据,如果没有数据,该函数也会阻塞直到数据接收完成。此处,我们不知道要接收多少个字节,给定了一个固定值。Receive成功返回后会将接收到的数据写入到我们提供的缓存中,即代码中的字节数组buf,并且返回实际接收到的字节数rcvLen。我们给定字节数组和字符串转换的编码方式为UTF8,所以此处通过UTF8将字节数组转换为字符串输出到控制台,并且调用Send函数将接收到的字节发送回客户端,完成数据回写操作。

客户端相对来说会简单一些,首先创建Socket对象,该对象调用Connect函数向指定IP地址和端口的节点发起连接请求,在Connect未完成前该函数会一直阻塞,服务端接收连接后,该函数返回,现在就可以使用开始创建的Socket对象进行数据收发操作了。

在代码中可以看到,InputLoop函数是一个死循环,该循环开始会等待用户向控制台输入数据,输入的数据会通过UTF8的编码方式转换为字节数组,socket对象调用Send函数将该字节数组发送出去,发送完成后,调用Receive,等待服务的回写数据,Receive返回,将转换后的字符串输出到控制台,完成回写,如此循环往复。

这两个模拟程序虽然简单,却包含了TCPSocket通信的全部流程,适合初尝网络编程的小伙伴玩味理解。

分享 转发
TOP
发新话题 回复该主题