C#中的Socket编程详解

目录
  • 一,网络基础
  • 二,Socket 对象
    • SocketType
    • ProtocolType
    • AddressFamily
  • 三,Bind() 绑定与 Connect() 连接
    • Bind()
    • Connect()
  • 四,Listen() 监听请求连接 和 Accept() 接收连接请求
    • Listen()
    • Accept()
  • 五,Receive() 与 Send()
    • Receive()
      • 参数
    • 返回
    • Send()
  • 六,释放资源
    • close()
  • 七,IPAddress 和IPEndPoint
    • IPAddress 用来处理IP地址、转换IP地址
    • IPEndPoint 表示IPAddress对象与端口的绑定

文章按照 Socket 的 创建、连接、传输数据、释放资源的过程来写。给出方法、参数的详细信息。

一,网络基础

说到 Socket,需要学习一下TCP/IP的知识,了解一下OSI 网络模。

推荐别人的文章,可以很快地了解这些。

https://www.jb51.net/article/234633.htm

https://www.jb51.net/article/234653.htm

二,Socket 对象

无论是服务器还是客户端,都要创建一个 SOCKET 对象,创建方法一致。

以下是常见的Socket对象创建实例

Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//监控 ip4 地址,套接字类型为 TCP ,协议类型为 TCP

其有三个构造函数

public Socket(SocketInformation socketInformation);
public Socket(SocketType socketType, ProtocolType protocolType);
public Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType);

第一个构造函数,SocketInformation 对象保存的是

Socket(SocketType, ProtocolType)

实质上跟第二个构造函数是一样的。就好像你可以直接把( 一个苹果 , 一个梨)直接放进篮子,也可以先给 水果包装好 再放进篮子里。

下面将解释所有参数的意义。

SocketType

指定 Socket 类的实例表示的套接字类型。

TCP 用主机的IP地址加上主机上的端口号作为 TCP 连接的端点,这种端点就叫做套接字(socket)或插口。 套接字用(IP地址:端口号)表示。

SocketType 是enum 类型,其字段如下


SocketType



对应的ProtocolType


描述


Unknown

-1
Unknown


指定未知的 Socket 类型。


Stream(使用字节流)


1


Tcp


支持可靠、双向、基于连接的字节流


Dgram(使用数据报)


2


Udp


面向无连接


Raw


3


Icmp、lgmp


支持对基础传输协议的访问


Rdm


4


支持无连接、面向消息、以可靠方式发送的消息,

并保留数据中的消息边界


Seqpacket


5

 
在网络上提供排序字节流的面向连接且可靠的双向传输

如需了解更详细的资料,请查阅Microsoft文档

地址:https://docs.microsoft.com/zh-cn/dotnet/api/system.net.sockets.sockettype?view=netframework-4.7.2

ProtocolType

表示协议类型,是一个enum 类型。

其所有字段如下


SocketType



对应的ProtocolType


描述


Unknown

-1
Unknown


指定未知的 Socket 类型。


Stream(使用字节流)


1


Tcp


支持可靠、双向、基于连接的字节流


Dgram(使用数据报)


2


Udp


面向无连接


Raw


3


Icmp、lgmp


支持对基础传输协议的访问


Rdm


4


支持无连接、面向消息、以可靠方式发送的消息,

并保留数据中的消息边界


Seqpacket


5

 
在网络上提供排序字节流的面向连接且可靠的双向传输

AddressFamily

表示使用的网络寻址方案,是一个 enum 类型。

地址类型
描述

AppleTalk 16
AppleTalk 地址。

Atm 22
本机 ATM 服务地址。

Banyan 21
Banyan 地址。

Ccitt 10
CCITT 协议(如 X.25)的地址。

Chaos 5
MIT CHAOS 协议的地址。

Cluster 24
Microsoft 群集产品的地址。

DataKit 9
Datakit 协议的地址。

DataLink 13
直接数据链接接口地址。

DecNet 12
DECnet 地址。

Ecma 8
欧洲计算机制造商协会 (ECMA) 地址。

FireFox 19
FireFox 地址。

HyperChannel 15
NSC Hyperchannel 地址。

Ieee12844 25
IEEE 1284.4 工作组地址。

ImpLink 3
ARPANET IMP 地址。

InterNetwork 2
IP 版本 4 的地址。

InterNetworkV6 23
IP 版本 6 的地址。

Ipx 6
IPX 或 SPX 地址。

Irda 26
IrDA 地址。

Iso 7
ISO 协议的地址。

Lat 14
LAT 地址。

Max 29
MAX 地址。

NetBios 17
NetBios 地址。

NetworkDesigners 28
支持网络设计器 OSI 网关的协议的地址。

NS 6
Xerox NS 协议的地址。

Osi 7
OSI 协议的地址。

Pup 4
PUP 协议的地址。

Sna 11
IBM SNA 地址。

Unix 1
Unix 本地到主机地址。

Unknown -1
未知的地址族。

Unspecified 0
未指定的地址族。

VoiceView 18
VoiceView 地址。

Socket 官方文档地址

https://docs.microsoft.com/zh-cn/dotnet/api/system.net.sockets.socket?redirectedfrom=MSDN&view=netframework-4.7.2

三,Bind() 绑定与 Connect() 连接

Bind() 用于绑定IPEndPoint 对象,在服务端使用。

Connect() 在客户端使用,用于连接服务端。

创建 Socket 对象后,接着绑定本地Socket / 连接服务端。

Bind()

public void Bind (System.Net.EndPoint localEP);

使用方法

        Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        IPAddress iP = IPAddress.Parse("127.0.0.1");

        //上面不重要,看下面
    //IPEndPoint iPEndPoint = new IPEndPoint(iP, 2300);
    //serverSocket.Bind(iPEndPoint);

       serverSocket.Bind(new IPEndPoint(iP, 2300))

你将在在本地创建IPEndPoint 对象,拥有此 ip:post 的访问权限。目的是绑定本地机器的某个端口,所有经过此端口的数据就归你管了。

Connect()

与远程主机建立连接。Connect() 有四个重载方法,不必关注,只需知道,必需提供 IP 和 Post 两个值。

使用方法

            IPAddress iP = IPAddress.Parse("127.0.0.1");
            IPEndPoint iPEndPoint = new IPEndPoint(iP, 2300);
            Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        //创建与远程主机的连接
            serverSocket.Connect(iPEndPoint);

四,Listen() 监听请求连接 和 Accept() 接收连接请求

Listen()

监控所有发送到此主机的、特点端口的连接请求。服务端使用,客户端不需要。

public void Listen (int backlog);

使用 Bind() 后,使用 Listen() 方法进行监控,backlog 参数指定可排队等待接受的传入连接的数量,即挂起的连接队列的最大长度。

示例

serverSocket.Listen(10);    //开始监听

Accept()

Accept() 以同步方式监听套接字,在连接请求队列中提取第一个挂起的连接请求,然后创建并返回一个新的 Socket 对象。

代码示例

            //创建终结点(EndPoint)
            IPAddress ip = IPAddress.Any;
            IPEndPoint ipe = new IPEndPoint(ip, 8000);

            //创建 socket 并开始监听
            Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            serverSocket.Bind(ipe);
            serverSocket.Listen(10);//开始监听

            //接受到client连接,为此连接建立新的socket,并接受信息
            Socket temp = serverSocket.Accept();//为新建连接创建新的socket
//关闭连接
temp.Close();

注意的是,每次建立连接是一个 Accept() 对象,如果你要进行 服务器-客户端互相通讯,应使用同一个 Accept() 对象。每个 Accept 对象都是 从客户端请求建立开始的,期间只要使用同一个 Accept 对象,都可以进行数据传输。

五,Receive() 与 Send()

  • Receive() 接收信息
  • Send() 发送信息

在服务端和客户端都使用这两个方法。

Receive()

使用示例

string recvStr = "";
byte[] recvBytes = new byte[1024];
int bytes;
bytes = temp.Receive(recvBytes, recvBytes.Length, 0);//从客户端接受信息
recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);

直接从微软那复制来的。

Receive(Byte[], Int32, Int32, SocketFlags, SocketError)
使用指定的 Socket,从绑定的 SocketFlags 接收数据,将数据存入接收缓冲区。

Receive(Byte[], Int32, Int32, SocketFlags)
使用指定的 Socket,从绑定的 SocketFlags 接收指定的字节数,存入接收缓冲区的指定偏移量位置。

Receive(IList<ArraySegment<Byte>>, SocketFlags, SocketError)
使用指定的 Socket,从绑定的 SocketFlags 接收数据,将数据存入接收缓冲区列表中。

Receive(Byte[], Int32, SocketFlags)
使用指定的 Socket,从绑定的 SocketFlags 接收指定字节数的数据,并将数据存入接收缓冲区。

Receive(Byte[], SocketFlags)
使用指定的 Socket,从绑定的 SocketFlags 接收数据,将数据存入接收缓冲区。

Receive(IList<ArraySegment<Byte>>, SocketFlags)
使用指定的 Socket,从绑定的 SocketFlags 接收数据,将数据存入接收缓冲区列表中。

Receive(IList<ArraySegment<Byte>>)
从绑定的 Socket 接收数据,将数据存入接收缓冲区列表中。

Receive(Byte[])
从绑定的 Socket 套接字接收数据,将数据存入接收缓冲区。

参数

Byte[] buffer

Byte类型的数组,它是存储接收到的数据的位置。

Int32 offset

buffer参数中的位置,用于存储所接收的数据。

Int32 size

要接收的字节数。

SocketFlags socketFlags

SocketFlags值的按位组合。

SocketError errorCode

一个SocketError对象,它存储套接字错误。

socketFlags 默认值为0 或 None ,笔者没有搞懂socketFlags 的应用场景。

返回

返回已成功读取的字节数。

Send()

send()跟Receive()用法相似,

示例代码如下

string str = "hello";
byte[] a = Encoding.UTF8.GetBytes(str);
send = socket.Send(a, 0);

发送/接收 都是使用 byte[] 字节流,所以接收时要进行转换。

六,释放资源

有 Accept 释放和 Socket 的释放。

Accept 是连接对象,一个 Socket 可能有数十个 Accept 连接。

使用 Shutdown( ) 方法可以 禁止 Asscpt 对象的操作(禁用某个 Socket 对象 的发送和接收)。

public void Shutdown (System.Net.Sockets.SocketShutdown how);

SocketShutdown 是一个 enum 类型。

实例

temp.Shutdown(SocketShutdown.Receive);
            //禁止接收
使用 描述
发送 Send 禁止对此发送Socket
接收 Receive 禁用对此接收Socket
消息和传送 Both 禁用发送和接收对此Socket

close()

会直接释放资源,Accept 和 Socket 对象都可以使用。使用后对象将彻底释放。

七,IPAddress 和IPEndPoint

//引入
using System.Net;

IPAddress 用来处理IP地址、转换IP地址

IPAddress.Parse() 方法可以把以小数点隔分的十进制 IP 表示转化成 IPAddress 类。

IPAddress ip = IPAddress.Parse("127.0.0.1");//把ip地址字符串转换为IPAddress类型的实例

IPAddress提供4个只读字段

  • Any 用于代表本地系统可用的任何IP地址
  • Broadcase用于代表本地网络的IP广播地址
  • Loopback用于代表系统的回送地址
  • None用于代表系统上没有网络接口

关于其类型的使用和全部方法、构造函数等,请查看文档Microsoft文档。

地址https://docs.microsoft.com/zh-cn/dotnet/api/system.net.ipaddress?view=netframework-4.7.2

IPEndPoint 表示IPAddress对象与端口的绑定

IPAddress ip = IPAddress.Any;              //把ip地址字符串转换为IPAddress类型的实例
IPEndPoint ipe = new IPEndPoint(ip, 8000);//用指定的端口和ip初始化IPEndPoint类的新实例

上面的代码,创建一个监控点,端口是 8000,对象是 本地所有IP。

另外,此类能够获取查看端口的值范围,除此外,此类没有太大意义。

Microsoft 文档地址https://docs.microsoft.com/zh-cn/dotnet/api/system.net.ipendpoint?view=netframework-4.7.2

到此这篇关于C#中的Socket编程详解的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • c# socket编程udp客户端实现代码分享

    复制代码 代码如下: Console.WriteLine("This is a Client, host name is {0}", Dns.GetHostName());//设置服务端终结点IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8001);//创建与服务端连接的套接字,指定网络类型,数据连接类型和网络协议Socket ConnSocket = new Socket(Address

  • C# Socket网络编程实例

    本文实例讲述了C# Socket网络编程技巧.分享给大家供大家参考.具体分析如下: 客户端要连接服务器:首先要知道服务器的IP地址.而服务器里有很多的应用程序,每一个应用程序对应一个端口号 所以客户端想要与服务器中的某个应用程序进行通信就必须要知道那个应用程序的所在服务器的IP地址,及应用程序所对应的端口号 TCP协议:安全稳定,一般不会发生数据丢失,但是效率低.利用TCP发生数据一般经过3次握手(所有效率低,自己百度三次握手) UDP协议:快速,效率高,但是不稳定,容易发生数据丢失(没有经过三

  • c# socket网络编程接收发送数据示例代码

    代码分2块,server端: 复制代码 代码如下: class Program    {        static void Main(string[] args)        {            TcpListener lsner = new TcpListener(9000);            lsner.Start();            Console.WriteLine("started in port: 9000");            while

  • 基于C#的socket编程的TCP异步的实现代码

    一.摘要 本篇阐述基于TCP通信协议的异步实现. 二.实验平台 Visual Studio 2010 三.异步通信实现原理及常用方法 3.1 建立连接 在同步模式中,在服务器上使用Accept方法接入连接请求,而在客户端则使用Connect方法来连接服务器.相对地,在异步模式下,服务器可以使用BeginAccept方法和EndAccept方法来完成连接到客户端的任务,在客户端则通过BeginConnect方法和EndConnect方法来实现与服务器的连接. BeginAccept在异步方式下传入

  • C#开发之Socket网络编程TCP/IP层次模型、端口及报文等探讨

    1.TCP/IP层次模型 当然这里我们只讨论重要的四层 01,应用层(Application):应用层是个很广泛的概念,有一些基本相同的系统级TCP/IP应用以及应用协议,也有许多的企业应用和互联网应用.http协议在应用层运行. 02,传输层(Tanspot):传输层包括UDP和TCP,UDP几乎不对报文进行检查,而TCP提供传输保证. 03,网络层(Netwok):网络层协议由一系列协议组成,包括ICMP.IGMP.RIP.OSPF.IP(v4,v6)等. 04,链路层(Link):又称为物

  • C# Socket编程实现简单的局域网聊天器的示例代码

    前言 最近在学习C# Socket相关的知识,学习之余,动手做了一个简单的局域网聊天器.有萌生做这个的想法,主要是由于之前家里两台电脑之间想要传输文件十分麻烦,需要借助QQ,微信或者其他第三方应用,基本都要登录,而且可能传输的文件还有大小限制,压缩问题.所以本聊天器的首要目标就是解决这两个问题,做到使用方便(双击启动即用),传文件无限制. 废话不多说,先上图.S-Chat是服务端,C-Chat是客户端,两者除了客户端首次启动后需要设置一下连接的IP地址外,无其他区别.操作与界面都完全相同,对于用

  • C#中异步Socket通信编程代码实例

    本文将在C#中Socket同步通信的基础上,分析和研究Socket异步编程的实现方法,目的是深入了解Socket编程的基本原理,增强对网络游戏开发相关内容的认识. 什么是Socket编程的异步是实现 所谓Socket编程的异步实现是指按照异步过程来实现Socket编程,那么什么是异步过程呢,我们把在完成了一次调用后通过状态.通知和回调来告知调用者的方式成为异步过程,换句话说,在异步过程中当调用一个方法时,调用者并不能够立刻得到结果,只有当这个方法调用完毕后调用者才能获得调用结果.这样做的好处是什

  • 详解C# Socket编程笔记

    看到这个题目,是不是很眼熟?在博客园里搜下,保证会发现关于这个东东的文章实在是太多了~~~真得是没有写得必要,而且我也有点懒得去琢磨字句.(看到这,肯定得来个转折的了,不然就看不到下文了,不是吗)但是,为了自己下一篇要写的文章做参考,还是有必要先补充一下socket基础知识. 注意:如果你已经接触过socket,那就没什么必要耽误时间看下去了.另外,如果发现其中任何错误,欢迎直接指出. 1.按惯例先来介绍下socket Windows中的很多东西都是从Unix领域借鉴过来的,Socket也是一样

  • C#中的Socket编程详解

    目录 一,网络基础 二,Socket 对象 SocketType ProtocolType AddressFamily 三,Bind() 绑定与 Connect() 连接 Bind() Connect() 四,Listen() 监听请求连接 和 Accept() 接收连接请求 Listen() Accept() 五,Receive() 与 Send() Receive() 参数 返回 Send() 六,释放资源 close() 七,IPAddress 和IPEndPoint IPAddress

  • Python Socket编程详解

    背景 关于Python Socket编程,首先需要了解几个计算机网络的知识,通过以下的几个问题,有助于更好的理解Socket编程的意义,以及整个框架方面的知识: TCP和UDP协议本质上的区别? TCP协议,面向连接,可靠,基于字节流的传输层通信协议:UDP协议无连接,不可靠,基于数据包的传输层协议. TCP协议在建立连接的过程需要经历三次握手,断开连接则需要经历四次挥手,而这建立连接的过程增加了传输过程中的安全性. 而建立连接的过程则会消耗系统的资源,消耗更多的时间,而相比较UDP协议传输过程

  • Python基础教程之tcp socket编程详解及简单实例

    Python tcp socket编程详解 初学脚本语言Python,测试可用的tcp通讯程序: 服务器: #!/usr/bin/env python # -*- coding: utf-8 -*- import socket import threading import time def tcplink(sock, addr): print('Accept new connection from %s:%s...' % addr); sock.send(b'Welcome!!!'); whi

  • JavaScript中的函数式编程详解

    函数式编程 函数式编程是一种编程范式,是一种构建计算机程序结构和元素的风格,它把计算看作是对数学函数的评估,避免了状态的变化和数据的可变,与函数式编程相对的是命令式编程.我们有这样一个需求,给数组的每个数字加一: // 数组每个数字加一, 命令式编程 let arr = [1, 2, 3, 4]; let newArr = []; for(let i = 0; i < arr.length; i++){ newArr.push(arr[i] + 1); } console.log(newArr)

  • Java Socket编程详解及示例代码

    Socket,又称为套接字,Socket是计算机网络通信的基本的技术之一.如今大多数基于网络的软件,如浏览器,即时通讯工具甚至是P2P下载都是基于Socket实现的.本文会介绍一下基于TCP/IP的Socket编程,并且如何写一个客户端/服务器程序. 餐前甜点 Unix的输入输出(IO)系统遵循Open-Read-Write-Close这样的操作范本.当一个用户进程进行IO操作之前,它需要调用Open来指定并获取待操作文件或设备读取或写入的权限.一旦IO操作对象被打开,那么这个用户进程可以对这个

  • IOS开发网络篇—Socket编程详解

    一.网络各个协议:TCP/IP.SOCKET.HTTP等 网络七层由下往上分别为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. 其中物理层.数据链路层和网络层通常被称作媒体层,是网络工程师所研究的对象: 传输层.会话层.表示层和应用层则被称作主机层,是用户所面向和关心的内容. http协议对应于应用层 tcp协议对应于传输层 ip协议对应于网络层 三者本质上没有可比性.  何况HTTP协议是基于TCP连接的. TCP/IP是传输层协议,主要解决数据如何在网络中传输:而HTTP是应用

  • PHP SOCKET编程详解

    1. 预备知识 一直以来很少看到有多少人使用php的socket模块来做一些事情,大概大家都把它定位在脚本语言的范畴内吧,但是其实php的socket模块可以做很多事情,包括做ftplist,http post提交,smtp提交,组包并进行特殊报文的交互(如smpp协议),whois查询.这些都是比较常见的查询. 特别是php的socket扩展库可以做的事情简直不会比c差多少. php的socket连接函数 1.集成于内核的socket 这个系列的函数仅仅只能做主动连接无法实现端口监听相关的功能

  • php的socket编程详解

    php的socket编程算是比较难以理解的东西吧,不过,我们只要理解socket几个函数之间的关系,以及它们所扮演的角色,那么理解起来应该不是很难了,在笔者看来,socket编程,其实就是建立一个网络服务的客户端和服务端,这和mysql的客户端和服务端是一样的,你只要理解mysql的客户端和服务端是怎么一回事,你就应该能够理解下面我要讲的东西吧. 关于socket编程所涉及到的网络协议,什么TCP啊,UDP啊,什么socket三次握手等等,这些网络协议网上有很详细的解释,这里不讲,只截个sock

  • Python中的面向对象编程详解(上)

    创建类 Python 类使用 class 关键字来创建.简单的类的声明可以是关键字后紧跟类名: 复制代码 代码如下: class ClassName(bases):     'class documentation string' #'类文档字符串'     class_suite #类体 实例化 通过类名后跟一对圆括号实例化一个类 复制代码 代码如下: mc = MyClass() # instantiate class 初始化类 'int()'构造器 def __int__(self):  

  • Node.js中的事件驱动编程详解

    在传统程编程模里,I/O操作就像一个普通的本地函数调用:在函数执行完之前程序被堵塞,无法继续运行.堵塞I/O起源于早先的时间片模型,这种模型下每个进程就像一个独立的人,目的是将每个人区分开,而且每个人在同一时刻通常只能做一件事,必须等待前面的事做完才能决定下一件事做什么.但是这种在计算机网络和Internet上被广泛使用的"一个用户,一个进程"的模型伸缩性很差.管理多个进程时,会耗费很多内存,上下文切换也会占用大量资源,这些对操作系统是个很大的负担,而且随着进程数的递增,会导致系统性能

随机推荐