C# Socket 使用教程
我在学习Socket时,总是感觉文章看不懂,视频又好长,所以留下这篇学习笔记,权当做同学间学习参考,与个人回顾吧.
简介
Socket(译做:管道/套接字)是一个便捷的类
用于封装通信时所涉及到复杂底层逻辑
也正因此我们就可以使用十分简便且直观的Socket类,并调用其中方法,就可轻松地实现数据通信/计算机间数据传输.
正文
所以,在Socket中,抽象出了服务端和客户端的概念,并提供了其所需要的方法.
服务端
服务端的Socket实现流程是这样的:
1.创建socket对象
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//first is 寻址方式(此处是Ipv4)
//second is the socket's type(此处是流式传输)
//And the thrid is the 传输协议(或者说是信息传输方法)
2.绑定端口IP
我这里是从我写好的Winform窗体中获取的字符串.
其中txtIP是本机(服务端设备)IP地址;txtPort里填的是端口号,
我这里就先用的是31201,大家也可以在10000-6000之间随便填(好像是)
socket.Bind(new IPEndPoint(IPAddress.Parse(txtIP.Text), int.Parse(txtPort.Text)));
//socket's Bind action need a IPEndPoint to bind the socket and the computer's ip and post
//(socket的Bing方法需要一个IPEndPoint来绑定socket和计算机的ip地址还有端口)
//so in the IPEndPoint we need a IPAddress and a int number(Post)
//所以在这个IPEndPoint中,我们需要一个IPAddress和一个数字(端口号)
3.开始侦听
socket.Listen(12233);//这个数字表示:同时排队的最大限制数量
//(这里是乱填的,一般改成100左右就可以了吧)
//是什么意思呢?:同时来了20000个链接请求,只能处理一个链接,
//队列里面放12233个等待链接的客户端,其他的返回错误消息。
4.开始接受客户端的链接
Socket proxSocket = serverSocket.Accept();//最好新开辟一个线程用来运行它
//this action is so especial(特殊) ,because the action will be 阻塞当前线程
//就是让它所在的线程停止工作,停在这个方法,
//直到侦测到客户端的请求才会返回一个代理Socket类型的变量
//(里面保存着客户端用来连接服务器端的socket的信息),然后继续往下执行
//So 这个方法每执行一次,往往就代表着,接收到了一个请求,并返回一个 代理Socket
//我们就可以读取这个代理socket的信息,并且调用它的Send方法,就可以实现信息的传递啦
5.接收数据
byte[] data = new byte[1024 * 1024];
proxSocket.Receive(data, 0, data.Length, SocketFlags.None);
string str = Encoding.UTF8.GetString(data, 0, len);//把拿到的二进制数字转换成字符串
//这个是拿到了代理的Socket对象,然后就Receive就行了
//挺抽象的是:这个也会像Accept一样阻塞住当前线程
//最后这个叫SocketFalgs枚举我也不知道是干啥的
并提供了向客户端传输数据的方法
byte[] data = Encoding.UTF8.GetBytes(txtMsg.Text);
proxSocket.Send(data, 0, data.Length, SocketFlags.None);//发送消息
//其中Encoding是一个类调用其中的静态UTF8方法会实例化一个Encoding的对象,
//然后调用其中的GetBytes方法,就会按照UTF8编码,把()中的内容转换为Bytes
//然后才能用Stream也就是流的传输模式来传输数据
客户端
客户端传输数据的逻辑和服务端十分类似,或者说,现在所提出的所谓从客户端与服务端两个方面去理解Socket,本身就是一个类的两种不同使用方法,所以,读到这里的同志,也请一定注意:Socket 本质上只是封装了通信功能的一个C#类,不要偏颇的仅仅以服务端和客户端的角度,去看待Socket,这是不全面的,服务端和客户端的功能,只是比较常见的需求,并应用了Socket技术,如此而已.
接下来是客户端的应用过程:
1.创建Socket对象
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
2.连接服务器端Socket
try//如果服务器的Listen队列已满,那么就会返回一个异常
{
socket.Connect(new IPEndPoint(IPAddress.Parse(txtIP.Text), int.Parse(txtPort.Text)));
//注意这里的txtIP.Text和txtPort.Text所填写的ip地址和端口都是服务端的
//逻辑上是:只要服务端的IP和端口固定了,那么客户端去找他就可以了,
//在连接之后,服务端就可以用,客户端连接后 自动生成的 代理Socket 与客户端进行消息的传递就可以了
}
catch
{
MessageBox.Show("当前服务器无法连接,请重试");
//如果愿意的话,可以把这段代码写成一个方法,然后在catch中调用自身,
//但是,要是一直连接不上的话,就怕一直递归下去会爆栈,所以还是有点危险的,
//有点影响程序鲁棒性,所以写个MessageBox得了
//暂停一秒,然后继续:
//Thread.Sleep(1000);
//调用自身方法体
3.接收服务器端消息
byte[] data = new byte[1024 * 1024];//一个可以存放1M数据的数组
int len = socket.Receive(data, 0, data.Length, SocketFlags.None);
//流式传输放到data里,len用来保存方法返回值,这个值是方法传递的字节数
string str = Encoding.UTF8.GetString(data, 0, len);
//服务和客户端双方一定要都用一套字符集,推荐UTF-8,
//如果是Defualt的话,他会按照系统默认字符集来传输/读取数据,
//字符集不同会出现乱码!
4.发送消息
byte[] data = Encoding.UTF8.GetBytes(txtMsg.Text);
socket.Send(data, 0, data.Length, SocketFlags.None);//发送消息
注意哦,我给出的代码例子,往往是可以直接在一个方法中使用的,但是,我不推荐这么做:
一是违反了面向对象的Single Responsibility Principle(单一责任原则);
二是,我给出的代码为了保证可读性(变量名可理解性)取名很直接.
尤其是在字符数组变量的data,存在变量名重复的问题,这时要么可以选择把他们放在不同的方法中,要么更改变量名,但是我更推荐把他们写在不同的方法中!
最后向大家说明一下,为什么客户端没有绑定IP地址和Post呢?
因为客户端在进行socket网络通信时,所携带的数据包就会包含自己的IP,而发送消息时所使用的端口则是由计算机自动分配的,
在第一次通信后,服务器就会保存相应的客户端ip和post到代理socket,以此来和客户端进行通信.
到了最最后,我想我应当给大家一些多线程的写法,以帮助大家写出更加丰满的程序,否则按照这个教程以上的知识,我们只能写出1对1的沟通程序,而这往往是具有一定局限性的.
Thread thread = new Thread(ParameterizedThrendStart((obj) = { }));//这里使用了有参委托
//ParameterizedThrendStart是官方提供的有参委托
//或者
//Thread thread = new Thread(ThrendStart(() = { }));
//ThrendStart是官方提供的无参委托
thread.IsBackground = true;
thread.Start(socket);
我想大家如果有一定C#基础的话可以看出,在这个线程的开辟中我们使用了,委托和Lambda表达式的相关知识,如果没学过可以去学,或者等我出学习日志,咱们一起学,咳咳,这些是后话
接下来更改了IsBackground的属性,将进程标志成了后台进程,然后开启了这个线程,线程将在执行完所有的ParmeterizedThrendStart委托中的方法后结束
C# IsBackground作用
这是前台进程和后台进程的区别
C#多线程系列(1):Thread
这是多线程系列课程
最最最后:
总结一下socket中常用的方法:
Bind
//绑定socket和ip地址与端口号
Listen
//表示的等待的链接上限,往往也与电脑配置有关,所以输一个超大的数,除了降低程序的安全性好像没啥大用,尽可能自己设置一个合理的上限吧
Accept
//等待连接,这个是服务端常用的一个方法,也是服务端和客户端通信最重要的一句话,创造连接,但是会阻塞线程,最好放在一个新的Thread里
Receive
//接收别的Thread给该程序(本机IP:程序占用端口)的数据,如果没有接收到,也会阻塞线程,最好也放在一个新的Thread里
Send
//Send用于发送某个东西,给这个socket,所以我们在客户端只需要服务端的IP地址,就是这个原因,我们得知道信息发送到哪去,而服务端,只需要调用Accept方法,等待客户端连接就可以了
Connect(new IPEndPoint(IPAddress.Parse(txtIP.Text), int.Parse(txtPort.Text)));
//这个是只有客户端才用的,因为你得知道要发给谁才行,然后就是自动与这个地址的Accept联系就可以了
但是话又说回来,Accept,Receive,还有Connect往往都是很容易抛异常的,所以最好try一下
总结:
实质上,我们去观察Socket,往往就能发现,我在本机运行和调用Socket中的方法,实现通信,而我要一定要给予socket的的往往是我们要联系的目标的IP地址和端口,而我们本地,socket就可以与系统沟通,然后便宜行事了.
(类似于我知道对方的手机号,就可以通信,但是我自己的手机号,由电话卡帮我保管)
而在实现的过程中,我们往往需要抽象出信息的:发送方与接收方,而我认为这也就是Tcp模式下socket的主要逻辑是,接收方绑定好端口等待连接,发送方调用Connect方法,寻找服务器,实际上就是接收方在等待,而发送方发送了沟通请求罢了
f5d37138-357b-46d3-ab69-85009e38c363
C# Socket 使用教程的更多相关文章
- 转:Python 的 Socket 编程教程
这是用来快速学习 Python Socket 套接字编程的指南和教程.Python 的 Socket 编程跟 C 语言很像. Python 官方关于 Socket 的函数请看 http://docs. ...
- Python——Socket 编程教程
这是用来快速学习 Python Socket 套接字编程的指南和教程.Python 的 Socket 编程跟 C 语言很像. Python 官方关于 Socket 的函数请看 http://docs. ...
- 【C++&爬虫】C++实现网络爬虫&socket初级教程
2019年了,发现以前的很多教程都不能用了. 我自己写的socket发给服务器总是返回301错误——资源永久转移.很多教程都是这样,困扰了我很久. 终于我发现了一篇能用的爬虫代码,参考MSDN以及众多 ...
- socket入门教程
Server.cs 服务端程序 using System; using System.Collections.Generic; using System.ComponentModel; using ...
- Python:socket编程教程
ocket是基于C/S架构的,也就是说进行socket网络编程,通常需要编写两个py文件,一个服务端,一个客户端. 首先,导入Python中的socket模块: import socket Pytho ...
- C#下利用封包、拆包原理解决Socket粘包、半包问题(新手篇)
介于网络上充斥着大量的含糊其辞的Socket初级教程,扰乱着新手的学习方向,我来扼要的教一下新手应该怎么合理的处理Socket这个玩意儿. 一般来说,教你C#下Socket编程的老师,很少会教你如何解 ...
- 「Python」socket指南
开始 网络中的 Socket 和 Socket API 是用来跨网络的消息传送的,它提供了 进程间通信(IPC) 的一种形式.网络可以是逻辑的.本地的电脑网络,或者是可以物理连接到外网的网络,并且可以 ...
- python socket 多人聊天室
参考来源(其实我从上面复制了一点):Python 的 Socket 编程教程 http://www.oschina.net/question/12_76126Python线程指南 http://ww ...
- 使用nodejs+express+socketio+mysql搭建聊天室
使用nodejs+express+socketio+mysql搭建聊天室 nodejs相关的资料已经很多了,我也是学习中吧,于是把socket的教程看了下,学着做了个聊天室,然后加入简单的操作mysq ...
- 【资料目录收藏】.NET开发必看资料53个 经典源码77个
简单描述:为大家整理了下载中心.net资料,都是比较热的,好评率比较高的,做了一个可收藏的下载目录,希望大家喜欢~ 基于.net构架的留言板项目大全源码 http://down.51cto.com/z ...
随机推荐
- 关于存入sessionStorage中boolean值拿出来为字符串
上面是html部分,然后定义了变量 定义方法 在mounted中获取,然后刷新页面,打印类型为字符串 解决办法
- .Net Core 管道底层源码实现
在 .NET Core 中,请求处理管道是一个中间件(Middleware)链,用于处理 HTTP 请求并生成响应.管道的底层实现基于 Microsoft.AspNetCore.Http 命名空间中的 ...
- 使用Docker部署的基于binlog实现Mysql8
概念 MySQL 基于 Binlog 的主从复制(Master-Slave Replication)是 MySQL 数据库中实现数据复制的一种机制.在这种复制模式下,主库(Master)记录所有对数据 ...
- Solution Set - “伸手向着拉格朗日点作别”
目录 0.「UR #9」「UOJ #133」电路手动分析 1.「UR #9」「UOJ #134」App 管理器 2.「UR #10」「UOJ #152」汉诺塔 3.「UNR #2」「UOJ #312」 ...
- C# 窗口鼠标穿透以及取消窗口鼠标穿透
private const int WS_EX_TRANSPARENT = 0x20; private const int GWL_EXSTYLE = -20; /// <summary> ...
- python读取excel的文件
1.安装依赖包,并且导入 pip install xlrd import xlrd 2.打开文件 path = r"C:\Users\xiao\Desktop\服务体系.xls" ...
- 【译】.NET 升级助手现在支持升级到集中式包管理
原文 | McKenna Barlow 翻译 | 郑子铭 最近,.NET 升级助手引入了一些有用的新功能和一种新的中央包管理 (CPM) 升级类型. .NET 升级助手可帮助您将解决方案升级到较新版本 ...
- 奥特曼autMan对接BBK-JD扫码登录+微信扫码登录
1.BBK京东扫码容器配置 首先进入root目录 cd /root 拉取镜像创建容器 docker run -dit \ -v $PWD/conf:/data/conf \ -v $PWD/logs: ...
- DataX - [01] 概述
DataX是阿里巴巴集团内被广泛使用的离线数据同步工具/平台.实现包括MySQL.Oracle.SQLServer.PostgreSQL.HDFS.Hive.ADS.HBase.TableStor ...
- 【vulhub】redis 4-unacc (redis未授权访问)
渗透环境 攻击机: IP: 192.168.66.130(Kali) 漏洞收录于:vulhub/redis/4-unacc 涉及知识点:redis未授权访问 影响版本:redis 版本 < ...