Socket点对点通信

简介:

前言

  Socket的英文原义是“孔”或“插座”,其实在网络编程中Socket就是这个意思,就像我们打电话,要首先知道对方的手机号一样,这个手机号就相当于一个Socket号、一个插座,在网络编程中就是ip+端口作为一个插座。

实现

  System.Net.Sockets命名空间下提供了Socket类,使.net下Socket变得很简单,Socket实现点对点通信有两种方式,一种是用服务器转接,所有的客户端都发送到服务端,客户端只做客户端;另一种是客户端是服务端又是服务端,就是既监听又发送信息。这篇就用第二种方式简单实现下,首先看下简单示意图:

  发送信息代码:

复制代码
 1   string message = txtMsg.Text.Trim();
 2   socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 3   string remoteIp = this.txtRemoteIP.Text;
 4   string remotePort = this.txtRemotePort.Text;
 5   int serverPort = Convert.ToInt32(remotePort);
 6   IPAddress serverIp = IPAddress.Parse(remoteIp);
 7   IPEndPoint remoteIep = new IPEndPoint(serverIp, serverPort);
 8   socketClient.Connect(remoteIep);
 9   toolStripStatusLabel1.Text = "与远程计算机" + remoteIp + ":" + remotePort + "建立连接!";
10 
11   byte[] byteMessage = Encoding.Default.GetBytes(message);
12   socketClient.Send(byteMessage);
13 
14   IPHostEntry host = Dns.GetHostEntry(GetServerIP());
15   string HostName = host.HostName;
16 
17   //发送信息 
18   string time1 = DateTime.Now.ToString();
19   listBox1.Items.Add(GetServerIP().ToString() + "(" + HostName + ") " + time1);
20   listBox1.Items.Add(message);
21 
22   socketClient.Shutdown(SocketShutdown.Both);
23   socketClient.Close();
复制代码

  IPEndPoint从这个单词的意思就可以看出是一个远端的地址信息,Connect方法根据这个地址建立链接,然后调用Send方法向远端发送信息,发送完信息之后要使用Shutdown指向当前Socket是否接受发送消息,下面列出SocketShutdown的枚举值:

描述

Send

禁用此 Socket 上的发送。

Receive

禁用此 Socket 上的接收。

Both

同时禁用此 Socket 上的发送和接收。

  Shutdown在msdn上解释是这样的:如果当前使用的是面向连接的Socket,则必须先调用 Shutdown 方法,然后才能关闭Socket这可以确保在已连接的套接字关闭之前,已发送和接收该套接字上的所有数据。Shutdown也是关闭的意思,其实关于Shutdown和Close我在网上找了很多资料,关于Shutdown解释的云里雾里,不是很明白,我这样理解不知道对不对,上面打电话的例子,按号码打通电话说完话按下挂机键,Shutdown的意思这样,确保信息已经发送。

  监听代码:

复制代码
 1    socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 2 
 3    IPAddress ServerIp = GetServerIP();
 4    IPEndPoint iep = new IPEndPoint(ServerIp, port);
 5    socketServer.Bind(iep);
 6 
 7    while (true)
 8    {
 9        try
10        {
11            socketServer.Listen(5);
12            allDone.Reset();
13            socketServer.BeginAccept(new AsyncCallback(AcceptCallback), socketServer);
14            allDone.WaitOne();
15        }
16        catch (SocketException ex)
17        {
18            toolStripStatusLabel1.Text += ex.ToString();
19        }
20    }
复制代码

  Bind与本机绑定开通这个“号码”以方便别人可以打进来,Listen(5)5的意思是最大的监听数,BeginAccept的意思是开始一个异步操作来接受一个传入的连接尝试,以异步方式接受连接将使您能够在单独的执行线程中发送和接收数据,回调方法使用EndAccept,并返回新的Socket对象。

复制代码
 1     //异步连接回调函数
 2     public void AcceptCallback(IAsyncResult ar)
 3     {
 4         Socket listener = (Socket)ar.AsyncState;
 5         Socket client = listener.EndAccept(ar);
 6         allDone.Set();
 7         StateObject state = new StateObject();
 8         state.workSocket = client;
 9         client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(readCallback), state);
10     }
11 
12     //异步接收回调函数
13     public void readCallback(IAsyncResult ar)
14     {
15         StateObject state = (StateObject)ar.AsyncState;
16         Socket handler = state.workSocket;
17         int bytesRead = handler.EndReceive(ar);
18         if (bytesRead > 0)
19         {
20             string strmsg = Encoding.Default.GetString(state.buffer, 0, bytesRead);
21 
22             //远端信息
23             EndPoint tempRemoteEP = handler.RemoteEndPoint;
24             IPEndPoint tempRemoteIP = (IPEndPoint)tempRemoteEP;
25             IPHostEntry host = Dns.GetHostByAddress(tempRemoteIP.Address);
26             string HostName = host.HostName;
27 
28             string ip = tempRemoteIP.Address.ToString() + "(" + HostName + ") " + DateTime.Now.ToString();
29             if (listBox1.InvokeRequired)
30             {
31                 MyDelegate md;
32                 md = new MyDelegate(ChangeText);
33                 listBox1.Invoke(md, ip, strmsg);
34             }
35         }
36     }
复制代码

  listener.EndAccept(ar)和handler.EndReceive(ar)取回远端Socket对象,这边注意下获取IPHostEntry对象并不是用GetHostEntry方法,而是GetHostByAddress方法,使用GetHostEntry方法会产生异常,异步调用传输对象StateObject:

复制代码
1      //异步传递的状态对象
2     public class StateObject
3     {
4         public Socket workSocket = null;
5         public const int BufferSize = 1024;
6         public byte[] buffer = new byte[BufferSize];
7     }
复制代码

  运行截图:

  完整代码:

  View Code

  程序下载:Socket点对点通信.rar

  附录:小菜学习编程-Winform系列(初学者)

 



本文转自田园里的蟋蟀博客园博客,原文链接:http://www.cnblogs.com/xishuai/p/3540200.html,如需转载请自行联系原作者

相关文章
|
2月前
|
数据处理 C# C++
如何使用C#和C++结构体实现Socket通信
如何使用C#和C++结构体实现Socket通信
|
4月前
|
网络协议 程序员 Python
揭秘Python网络编程:深入理解Socket通信
在当今信息时代,网络通信已经成为人们生活中不可或缺的一部分。而Python作为一种高效、易用的编程语言,自然也能够很好地支持网络编程和Socket通信。本文将介绍Python网络编程与Socket通信的相关知识,包括Socket通信模型、Socket编程接口、网络套接字等内容。
|
4月前
|
网络协议 开发者 Python
Python网络编程与Socket通信:连接世界的无限可能
在当今数字化时代,Python作为一种强大的编程语言,通过网络编程与Socket通信为我们打开了连接世界的无限可能。本文将深入探讨Python网络编程的基础知识、Socket通信的原理以及实际应用,帮助读者更好地理解并运用这一技术。
|
4月前
|
网络协议
【Netty 网络通信】Socket 通信原理
【1月更文挑战第9天】【Netty 网络通信】Socket 通信原理
|
6月前
|
存储 Cloud Native Linux
C++封装了socket通信类
C++封装了socket通信类
|
7月前
|
存储
14.10 Socket 套接字选择通信
对于网络通信中的服务端来说,显然不可能是一对一的,我们所希望的是服务端启用一份则可以选择性的与特定一个客户端通信,而当不需要与客户端通信时,则只需要将该套接字挂到链表中存储并等待后续操作,套接字服务端通过多线程实现存储套接字和选择通信,可以提高服务端的并发性能,使其能够同时处理多个客户端的请求。在实际应用场景中,这种技术被广泛应用于网络编程、互联网应用等领域。在服务端启动时,创建套接字并进行绑定,然后开启一个线程(称为主线程)用于监听客户端的连接请求。主线程在接收到新的连接请求后,会将对应的套接字加入一个数据结构(例如链表、队列、哈希表等)中进行存储。同时,主线程会将存储套接字的数据结构传递给
25 1
14.10 Socket 套接字选择通信
|
7月前
14.5 Socket 应用组播通信
组播通信是一种基于UDP协议的网络通信方式,它允许发送方将消息同时传递给多个接收方。在组播通信中,发送方和接收方都会加入一个共同的组播组,这个组播组对应一个特定的IP地址,所有加入该组播组的主机都能够接收到发送方发送的消息。组播通信可以有效地减少网络流量和网络负载,因为在传统的点对点通信方式下,每个消息都需要单独传输到每个接收方,而在组播通信中,每个消息只需要传输一次,就可以同时传递给多个接收方。在使用组播模式时,需要在套接字上使用`setsockopt()`函数来设置套接字的`IP_MULTICAST_IF`选项,指定本地主机的出站接口地址,用于发送组播数据包。此外,还可以设置`IP_ADD
72 0
14.5 Socket 应用组播通信
|
8月前
|
Java
Java的Socket进行通信
下面是一个使用Java的Socket进行通信的简单示例
|
16天前
|
存储 网络协议 关系型数据库
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
|
1月前
|
网络协议 Unix Linux
Socket通信详细介绍1
Socket通信详细介绍
33 0