前面已经简要介绍了一下Socket和一些相关知识,但是我想说明一点,网络通信不是只能用Socket,比如命名空间System.Net.Sockets就提供了制作Sockets网络应用程序的几个相关类,Socket类只是其一,但是个人感觉它比其他几个强大。
1.Socket类
主要用于管理连接,实现Berkeley通信端套接字接口。定义了绑定、连接网络端点及传输数据所需要的各种方法,提供处理端点连接传输等细节所需要的功能。
2.TcpListener类和TcpClient类
TcpClient类用于在同步阻止模式下通过网络来连接、发送和接受流数据。
TcpListener类用于在阻止同步模式下侦听和接受传入的连接请求。
3.UdpClient类
UdpClient类用于在阻止同步模式下通过网络来发送和接受无连接的UDP数据报。
下面就展示一下Socket简单通信的具体实现,UDP和TCP两种。
先来简单一些的UDP通信。由于这个实在是没什么太难之处就写的控制台,这个程序两端其实是一样的,UDP通信是没有客户端和服务器端之分的,分服务区端和客户端只是给两个一样的小程序编个号。(hh)
/// <summary>
/// 发送消息
/// </summary>
static void sendMsg()
{
EndPoint point = new IPEndPoint(IPAddress.Parse("192.168.0.104"), 9500);
while (true)
{
string msg = Console.ReadLine();
client.SendTo(Encoding.UTF8.GetBytes(msg), point);
}
}
/// <summary>
/// 接收消息
/// </summary>
static void ReciveMsg()
{
while (true)
{
EndPoint point = new IPEndPoint(IPAddress.Any, 0); //用来保存对方的ip和端口号
byte[] buffer = new byte[1024];
int length = client.ReceiveFrom(buffer, ref point); //接收数据报
string message = Encoding.UTF8.GetString(buffer, 0, length);
Console.WriteLine(point.ToString()+":" + message);
}
}
这是接受和发送数据报的两个函数。
public static Socket client;
static void Main(string[] args)
{
client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
client.Bind(new IPEndPoint(IPAddress.Parse("192.168.0.104"), 10050));
Console.WriteLine("---------客户端已开启------");
Thread t = new Thread(sendMsg);
t.Start();
Thread t2 = new Thread(ReciveMsg);
t2.Start();
t2.IsBackground = true;
}
然后就直接在主函数里创建两个线程,一个Socket,开始等待接收消息和发送消息。
服务器端和这个一模一样,我就不贴了。这个其实就是局域网聊天小程序
知道对方的端口和IP,在一个局域网内就可以通信了,端口一般取1024以上的,自己也可以慢慢试。
————————————————————————————————
可以看出,UDP通信只需要一个Socket就可以实现通信了,这种方式不关心对方是否在线,就像发邮件一样,知道你是谁,你的邮箱地址是什么(IP和端口),然后我就直接发过去,效率高,但是会可能会丢失数据,因此视频什么的就可以用这种方式传输,毕竟丢失一些数据我们又怎么可能看出来呢。
效果图:
—————————————————————————————————
再来看看TCP通信的。
首先服务器端必须要有一个监听Socket,监听是否有客户端的连接请求。
/// <summary>
/// 服务端开始监听
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button_Listening_Click(object sender, EventArgs e)
{
this.textBox1.Text = GetLocalIP(); //自动获取IP
IPAddress ip = IPAddress.Parse(textBox1.Text); //服务端IP地址
IPEndPoint point = new IPEndPoint(ip, int.Parse(textBox2.Text)); //IP和端口号
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //创建监听用的Socket
try
{
socket.Bind(point); //socket监听主机上指定端口并绑定
socket.Listen(5); //可允许队列最多5个客户端
ShowMessage("服务器开始监听");
Thread thread = new Thread(AcceptInformation);
thread.IsBackground = true;
thread.Start(socket);
}
catch (Exception ex)
{
ShowMessage(ex.Message);
}
如果监听到请求就接收请求并再创建一个Socket用来通信。
/// <summary>
/// 接收客户端请求信息
/// </summary>
/// <param name="sender"></param>
public void AcceptInformation(object sender)
{
Socket socket = sender as Socket;
while (true)
{
try
{
Socket socket1 = socket.Accept(); //创建通信用的socket
string point = socket1.RemoteEndPoint.ToString(); //获取端口结点
ShowMessage(point + "连接成功");
listBox1.Items.Clear();
listBox1.Items.Add(point);
dictory.Add(point, socket1);
Thread accept = new Thread(ReceiveMessage); //接受消息
accept.IsBackground = true;
accept.Start(socket1);
}
catch (Exception ex)
{
ShowMessage(ex.Message);
}
}
}
然后就是发送消息与接受消息的实现了。
/// <summary>
/// 发送消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
try
{
ShowMessage(GetLocalIP().ToString ()+":"+txtMsg.Text); //服务端显示消息
string point = listBox1.Text; //之前存储的IP
byte[] buffer = Encoding.UTF8.GetBytes(txtMsg.Text);
dictory[point].Send(buffer); //发送消息 注:用之前集合中存储的键值,也就是端口是键,socket是值
}
catch (Exception ex)
{
ShowMessage(ex.Message);
}
}
/// <summary>
/// 接受消息
/// </summary>
/// <param name="sender"></param>
public void ReceiveMessage(object sender)
{
Socket client = sender as Socket;
while (true)
{
try
{
byte[] Byte = new byte[1024 * 1024]; //定义数组用来存放从客户端接受到的数据(大小为1M)
int Mid = client.Receive(Byte); //将接受过来的数据存放到Byte中,并得到接受数据的长度
string str = Encoding.UTF8.GetString(Byte, 0, Mid); //将字节转换成字符串
ShowMessage(client.RemoteEndPoint.ToString() + ":" + str);
}
catch (Exception ex)
{
ShowMessage(ex.Message);
}
}
}
额,为了省事,我还写了一个获取本地IP的函数
/// <summary>
/// 获取本地IP
/// </summary>
/// <returns></returns>
public string GetLocalIP()
{
try
{
string HostName = Dns.GetHostName();
IPHostEntry hostEntry = Dns.GetHostEntry(HostName);
for (int j = 0; j < hostEntry.AddressList.Length; j++)
{
if(hostEntry .AddressList [j].AddressFamily ==AddressFamily.InterNetwork )
return hostEntry.AddressList[j].ToString();
}
return "Error";
}
catch (Exception ex)
{
ShowMessage("获取本机IP失败!"+ex.Message);
return "Error";
}
}
客户端更简单就不贴了。(所有源码我就放在文末,有需要者自取吧)
————————————————————————————————
通过TCP通信的例子可以发现它至少需要两个Socket,一个用来监听,一个用来通信,监听是为了两方能够成功连接,这就是比UDP安全的地方,也是速度更慢的地方。
放一下效果图吧
需要注意一下,服务器端发消息时要选中一个客户端,否则就会出现图中那种错误“未包含在字典中”。
这个程序还有很多不足之处,但是仅仅当作学习的例子吧,在一方退出时会
一直抽风,应该会干扰其他的客户端(我还没测过)。除此之外,Socket通信还可以传图片,传文件,放广播等(具体的还在研究中,搞出来了可以分享给大家)。我写这个仅仅用于学习,有些代码肯定也是借鉴了其他人的,今后有时间再改进了。。。。。
—————————————————————————————————