C# Winform 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 }

运行截图:

完整代码:

1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8 using System.Windows.Forms;
9
10 using System.Threading;
11 using System.Net;
12 using System.Net.Sockets;
13
14 namespace ClientSocket
15 {
16 public partial class Form1 : Form
17 {
18 Socket socketClient;
19 Thread mythread;//创建线程
20 Socket socketServer;
21 int port = 8080;//定义侦听端口号
22 public static ManualResetEvent allDone = new ManualResetEvent(false);
23 public delegate void MyDelegate(string ip,string message);
24
25 public Form1()
26 {
27 InitializeComponent();
28 }
29 private void Form1_Load(object sender, EventArgs e)
30 {
31 mythread = new Thread(new ThreadStart(BeginListen));
32 mythread.Start();
33
34 txtRemoteIP.Text = GetServerIP().ToString();
35 }
36
37 #region server
38 //获取本机IP地址
39 public static IPAddress GetServerIP()
40 {
41 IPHostEntry ieh = Dns.GetHostEntry(Dns.GetHostName());
42 foreach (IPAddress item in ieh.AddressList)
43 {
44 if (item.ToString().IndexOf("192.168.0.")>=0)
45 {
46 return item;
47 }
48 }
49 return null;
50 }
51
52 //异步传递的状态对象
53 public class StateObject
54 {
55 public Socket workSocket = null;
56 public const int BufferSize = 1024;
57 public byte[] buffer = new byte[BufferSize];
58 }
59
60 //监听
61 private void BeginListen()
62 {
63 socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
64
65 IPAddress ServerIp = GetServerIP();
66 IPEndPoint iep = new IPEndPoint(ServerIp, port);
67 socketServer.Bind(iep);
68
69 while (true)
70 {
71 try
72 {
73 socketServer.Listen(5);
74 allDone.Reset();
75 socketServer.BeginAccept(new AsyncCallback(AcceptCallback), socketServer);
76 allDone.WaitOne();
77 }
78 catch (SocketException ex)
79 {
80 toolStripStatusLabel1.Text += ex.ToString();
81 }
82 }
83 }
84
85 //异步连接回调函数
86 public void AcceptCallback(IAsyncResult ar)
87 {
88 Socket listener = (Socket)ar.AsyncState;
89 Socket client = listener.EndAccept(ar);
90 allDone.Set();
91 StateObject state = new StateObject();
92 state.workSocket = client;
93 client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(readCallback), state);
94 }
95
96 //异步接收回调函数
97 public void readCallback(IAsyncResult ar)
98 {
99 StateObject state = (StateObject)ar.AsyncState;
100 Socket handler = state.workSocket;
101 int bytesRead = handler.EndReceive(ar);
102 if (bytesRead > 0)
103 {
104 string strmsg = Encoding.Default.GetString(state.buffer, 0, bytesRead);
105
106 //远端信息
107 EndPoint tempRemoteEP = handler.RemoteEndPoint;
108 IPEndPoint tempRemoteIP = (IPEndPoint)tempRemoteEP;
109 IPHostEntry host = Dns.GetHostByAddress(tempRemoteIP.Address);
110 string HostName = host.HostName;
111
112 string ip = tempRemoteIP.Address.ToString() + "(" + HostName + ") " + DateTime.Now.ToString();
113 if (listBox1.InvokeRequired)
114 {
115 MyDelegate md;
116 md = new MyDelegate(ChangeText);
117 listBox1.Invoke(md, ip, strmsg);
118 }
119 }
120 }
121
122 public void ChangeText(string ip,string message)
123 {
124 listBox1.Items.Add(ip);
125 listBox1.Items.Add(message);
126 }
127
128 #endregion
129
130 #region client
131 //发送信息
132 private void btn_Send_Click(object sender, EventArgs e)
133 {
134 try
135 {
136 string message = txtMsg.Text.Trim();
137 socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
138 string remoteIp = this.txtRemoteIP.Text;
139 string remotePort = this.txtRemotePort.Text;
140 int serverPort = Convert.ToInt32(remotePort);
141 IPAddress serverIp = IPAddress.Parse(remoteIp);
142 IPEndPoint remoteIep = new IPEndPoint(serverIp, serverPort);
143 socketClient.Connect(remoteIep);
144 toolStripStatusLabel1.Text = "与远程计算机" + remoteIp + ":" + remotePort + "建立连接!";
145
146 byte[] byteMessage = Encoding.Default.GetBytes(message);
147 socketClient.Send(byteMessage);
148
149 IPHostEntry host = Dns.GetHostEntry(GetServerIP());
150 string HostName = host.HostName;
151
152 //发送信息
153 string time1 = DateTime.Now.ToString();
154 listBox1.Items.Add(GetServerIP().ToString() + "(" + HostName + ") " + time1);
155 listBox1.Items.Add(message);
156
157 socketClient.Shutdown(SocketShutdown.Both);
158 socketClient.Close();
159 }
160 catch
161 {
162 toolStripStatusLabel1.Text = "无法连接到目标计算机!";
163 return;
164 }
165 }
166
167 private void btnClose_Click(object sender, EventArgs e)
168 {
169 Application.Exit();
170 }
171 #endregion
172 }
173 }

程序下载:Socket点对点通信.rar
C# Winform Socket点对点通信的更多相关文章
- 小菜学习Winform(三)Socket点对点通信
前言 Socket的英文原义是“孔”或“插座”,其实在网络编程中Socket就是这个意思,就像我们打电话,要首先知道对方的手机号一样,这个手机号就相当于一个Socket号.一个插座,在网络编程中就是i ...
- winform socket编程之TCPListener
运行结果: 服务端代码 using System; using System.Collections.Generic; using System.ComponentModel; using Syste ...
- 【转】Winform Socket通信
Socket相关概念[端口] 在Internet上有很多这样的主机,这些主机一般运行了多个服务软件,同时提供几种服务.每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务(应 ...
- Winform Socket通信
Socket相关概念[端口] 在Internet上有很多这样的主机,这些主机一般运行了多个服务软件,同时提供几种服务.每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务(应 ...
- 小菜学习编程-Winform系列(初学者)
前言 记得上次写<小菜的程序员道路(二)>,这篇文章的时候说过,要把工作以来整理的编程知识分享给大家,因为这半年来的工作实在是忙,现在也在忙着公司产品上线,但是答应的一定要实现,大家看我上 ...
- 初学c# -- 学习笔记 小结
学了到了好些东西, 做了一些练习. 一.C# winform Socket 1.程序主要部分只是用了 Panel.Picturebox.Label.RicheditBox四个组件,滚动条.编辑框什么的 ...
- .Net2.0 --Winform结合WebBrowser控件和Socket老技术来实现另类Push~
原文:.Net2.0 --Winform结合WebBrowser控件和Socket老技术来实现另类Push~ 目前的企业级开发比较流行的是Web2.0技术,但是由于Web技术基于请求--响应的交互模式 ...
- 简单的Socket通信(简单的在线聊天)---winform
注:本博客适合刚开始学习winform程序的初学者,大牛请绕道(跪求大牛指导文中不足) .....10w字废话自动省略,直接开始正题. 首先从最基本的建立winform开始(本项目用的Vs2017) ...
- 基于.net C# Socket WinForm MQTT 客户端开发
1.什么是MQTT? MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的&quo ...
- C#版 Winform界面 Socket编程 Client客户端
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
随机推荐
- 以下总结了Java一些面试前准备和技术参考题,希望对你有所帮助
以下真实模拟JAVA面试场景: 感谢您参加我们的面试: 以下是我们总结一些面试前准备和技术参考题,希望对你有所帮助. 首先,你需要先准备下工作相关的自我介绍,包括以下内容: 几年 Java 开发经验, ...
- Apifox:成熟的测试工具要学会自己写接口文档
好家伙, 在开发过程中,我们总是避免不了进行接口的测试, 而相比手动敲测试代码,使用测试工具进行测试更为便捷,高效 今天发现了一个非常好用的接口测试工具Apifox 相比于Postman,他还拥有一个 ...
- mvc-mvp-mvvm架构调研及实现--分布式课程思考题--zzb
目录 I. 引言 2 研究背景和动机 2 问题陈述和研究目标 2 II. 相关工作 3 研究现状和相关技术 3 MVC模式的研究现状和相关技术: 3 MVP模式的研究现状和相关技术: 4 MVVM ...
- 按值传递,引用传递 浅析java String ,对象与对象引用的区别
目录 一.前言 二.何谓对象? 三.何谓对象引用? 四.创建对象 Vehicle veh1 = new Vehicle(); 五.参数传值 六.Java Sting 最后!有错误的地方欢迎指正 一.前 ...
- GB 2312字符集:中文编码的基石
一.GB 2312字符集的背景 GB 2312字符集是中国国家标准委员会于1980年发布的一种中文字符集,是中国大陆最早的中文字符集之一.GB 2312字符集的发布填补了中国大陆中文编码的空白,为中文 ...
- Failed to collect dependencies at com.oneconnect......-Intellij-IDEA-使用maven打包采坑记录
一.问题由来 由于刚开始使用Intellij-IDEA,使用不是很熟练,因此使用过程中出现各种各样的问题.最近开发过程中,准备使用IDEA打包项目发布到测试服务器,报错信息如下: Failed to ...
- Prettier 和 ESLint 冲突解决方案 eslint-config-prettier eslint-plugin-prettier
划重点 eslint-config-prettier 禁用 eslint 冲突配置 eslint-plugin-prettier Prettier先格式化 (默认是先eslint格式化,再Pretti ...
- 基于ESP8266的JSON解析实例分析
什么是JSON? JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.采用完全独立于编程语言的文本格式来存储和表示数据.其简洁和层次结构清晰的特点使得 J ...
- 基于C#的壁纸管理器(插件版) - 开源研究系列文章
这几天无聊,想到原来的壁纸管理器应用能够实现成插件的形式,然后思考了一下,打算把原来壁纸管理器的代码用插件形式来进行实现,于是经过几天的努力,终于完成了插件版的壁纸管理器.以前有写过C#的插件的例子( ...
- 模板函数中的const
所有讨论都是底层const指针或引用,顶层const不会传递进模板. 模板中有const,不管传进来是否是const,T都是非const类型. template<typename T> v ...