C#.net同步异步SOCKET通讯和多线程总结(转)

C#.net同步异步SOCKET通讯和多线程总结

来源:http://www.cnblogs.com/Silverlight_Team/archive/2009/03/13/1411136.html

同步套接字通信

Socket支持下的网上点对点的通信

服务端实现监听连接,客户端实现发送连接请求,建立连接后进行发送和接收数据的功能

服务器端建立一个socket,设置好本机的ip和监听的端口与socket进行绑定,开始监听连接请求,当接收到连接请求后,发送确认,同客户端建立连接,开始与客户端进行通信。

客户端建立一个socket,设置好服务器端的IP和提供服务的端口,发出连接请求,接收到服务的确认后,尽力连接,开始与服务器进行通信。

服务器端和客户端的连接及它们之间的数据传送均采用同步方式。

 

Socket

Socket是tcp\ip网络协议接口。内部定义了许多的函数和例程。可以看成是网络通信的一个端点。在网络通信中需要两个主机或两个进程。通过网络传递数据,程序在网络对话的每一端需要一个socket。

       Tcp/IP传输层使用协议端口将数据传送给一个主机的特定应用程序,协议端口是一个应用程序的进程地址。传输层模块的网络软件模块要于另一个程序通信,它将使用协议端口,socket是运行在传输层的api,使用socket建立连接发送数据要指定一个端口给它。

Socket:

Stream Socket流套接字 Socket提供双向、有序、无重复的数据流服务,出溜大量的网络数据。

Dgram socket数据包套接字 支持双向数据流,不保证传输的可靠性、有序、无重复。

Row socket 原始套接字 访问底层协议

建立socket 用C#

命名空间:using System.Net;using System.Net.Socket;

构造新的socket对象:socket原型:

Public socket (AddressFamily addressFamily,SocketType sockettype,ProtocolType protocolType)

AddressFamily 用来指定socket解析地址的寻址方案。Inte.Network标示需要ip版本4的地址,Inte.NetworkV6需要ip版本6的地址

SocketType参数指定socket类型Raw支持基础传输协议访问,Stream支持可靠,双向,基于连接的数据流。

ProtocolType表示socket支持的网络协议

 

定义主机对象:

IPEndPoint类:IPEndPoint构造方法  位置:System.Net

原型:1)   public IPEndPoint(IPAddress address,int port)     2)public IPEndPoint(long address,int port) 参数1整型int64如123456,参数2端口int32

主机解析:

利用DNS服务器解析主机,使用Dns.Resolve方法

原型:public static IPHostEntry Resolve(string hostname) 参数:待解析的主机名称,返回IPHostEntry类值,IPHostEntry为Inte.Net主机地址信息提供容器,该容器提供存有IP地址列表,主机名称等。

Dns.GetHostByName获取本地主机名称

原型:public static IPHostEntry GetHostByName(string hostname)

GetHostByAddress

原型:1)public static IPHostEntry GetHostByAddress(IPAddress address) 参数:IP地址 2)public static IPHostEntry GetHostByAddress(string address) IP地址格式化字符串

 

端口绑定和监听:

同步套接字服务器主机的绑定和端口监听

Socket类的Bind(绑定主机),Listen(监听端口),Accept(接收客户端的连接请求)

Bind:原型:public void Bind(EndPoint LocalEP)参数为主机对象 IPEndPoint

Listen:原型:public void Listen(int backlog) 参数整型数值,挂起队列最大值

accept:原型:public socket accept() 返回为套接字对象

演示程序:

IPAddress myip=IPAddress.Parse(“127.0.0.1”);

IPEndPoint myserver=new IPEndPoint(myip,2020);

Socket sock=new Socket(AddressFamily.Inte.Network,SocketType.Stream,ProtocolType.Tcp);

Sock.Bind(myserver);

Sock.Listen(50);

Socket bbb=sock.Accept();

发送数据:方法1:socket类的send方法二.NetworkStream类Write

send原型:public int Send(byte[] buffer) 字节数组 

public int Send(byte[],SocketFlags)原型2说明,SocketFlags成员列表:DontRoute(不使用路由表发送),MaxIOVectorLength(为发送和接收数据的wsabuf结构数量提供标准值)None 不对次调用使用标志) OutOfBand(消息的部分发送或接收)Partial(消息的部分发送或接收) Peek(查看传入的消息)

原型三:public int Send(byte[],int,SocketFlags) 参数二要发送的字节数

原型四:public int Send(byte[],int,int,SocketFlags) 参数二为Byte[]中开始发送的位置

演示:

Socket bbb=sock.Accept();

Byte[] bytes=new Byte[64];

string send="aaaaaaaaaaaa";

bytes=System.Text.Encoding.BigEndianUnicode.GetBytes(send.ToCharArray());

bbb.Send(bytes,bytes.length,0);//将byte数组全部发送

.NetWordStream类的Write方法发送数据

原型:public override void write(byte[] buffer,int offset,int size) 字节数组,开始字节位置,总字节数

 

Socket bbb=sock.Accept();

.NetWorkStream stre=new NewWorkStream(bbb);

Byte[] ccc=new Byte[512];

string sendmessage="aaaaaaaaaaaaaa";

ccc=System.Text.Encoding.BigEndianUnicode.GetBytes(sendmessage);

stre.Write(ccc,0,ccc.length);

接收数据:Socket类Receive.NetworkStream类Read

Socket类Receive方法

原型:public int Receive(byte[] buffer)   

2)public int Receive(byte[],SocketFlags)

3)public int Receive(byte[],int,SocketFlags)   

4)public int Receive(byte[],int,int,SocketFlags)

.....

Socket bbb=sock.Accept();

........

Byte[] ccc=new Byte[512];

bbb.Receive(ccc,ccc.Length,0);

string rece=System.Text.Encoding.BigEndianUnicode.GetString(ccc);

richTextBox1.AppendText(rece+"\r\n");

 

.NetworkStream类的Read方法接收数据

public override int Read(int byte[] buffer,int offset,int size)

 

演示:bbb=sock.Accept();

.......

.NetworkStream stre=new.NetworkStream(bbb);

Byte[] ccc=new Byte[512];

stre.Read(ccc,0,ccc.Length);

string readMessage=System.Text.Encoding.BigEndianUnicode.GetString(ccc);

线程

线程创建:System.Threading空间下的Thread类的构造方法:

原型:public Thread(ThreadStart start) ThreadStart类型值     

       Thread thread=new Thread(new ThreadStart(accp));

       Private void accp(){}//使用线程操作

线程启动

Thread thread=new Thread(new ThreadStart(accp));

线程暂停与重新启动

启动线程使用Thread.Sleep是当前线程阻塞一段时间Thread.Sleep(Timeout.Infinite)是线程休眠,直到被调用Thread.Interrrupt的另一个线程中断或被Thread.Abort中止。

一个线程不能对另一个调用Sleep,可以使用Thread.Suspend来暂停线程,当线程对自身调用Thread.Suspend将阻塞,直到该线程被另一个线程继续,当一个线程对另一个调用,该调用就成为使另一个线程暂停的非阻塞调用。调用Thread.Resume使另一个线程跳出挂起状态并使该线程继续执行,而与调用Thread.Suspend的次数无关

线程休眠:Thread.Sleep(10000);

线程挂起:Thread thread=new Thread(new ThreadStart(accp));

                Thread.start();

                Thread.Suspend();

重新启动:Thread thread=new Thread(new ThreadStart(accp));

               Thread.start();

               Thread.Suspend();

               Thread.Resume();

阻塞线程的方法:thread.Join使用一个线程等待另一个线程停止

Thread.Join

Public void Join();

Public void Join(int millisecondsTimeout);毫秒

Public bool Join(TimeSpan timeout);时间间隔类型值

实例:Thread thread=new Thread(new ThreadStart(accp));

              Thread.start();

              Thread.Join(10000);

线程销毁:

Thread.Abort,Thread.Interrupt

Abort方法引发ThreadAbortException,开始中止此线程的过程,是一个可以由应用程序代码捕获的特殊异常,ResetAbort可以取消Abort请求,可以组织ThreadAbortException终止此线程,线程不一定会立即终止,根本不终止。

对尚未启动的线程调用Abort,则当调用Start时该线程将终止。对已经挂起的线程调用Abort,则该线程将继续,然后终止。对阻塞或正在休眠的线程调用Abort,则该线程被中断,然后终止。

Thread类的Abort方法:

Public void Abort()

Public void Abort(object stateinfo);

演示:

Thread thread=new Thread(new ThreadStart(accp));

Thread.Start();

Thread.Abort();

Thread.Join(10000);

 

Socket编程原理:

Unix的i/o命令集,模式为开-读/写-关 open write/read close

用户进程进行i/o操作

用户进程调用打开命令,获取文件或设备的使用权,并返回描述文件或设备的整数,以描述用户打开的进程,该进程进行读写操作,传输数据,操作完成,进程关闭,通知os对哪个对象进行了使用。

Unix网络应用编程:BSD的套接字socket,unix的System V 的TLI。

套接字编程的基本概念:

网间进程通信:源于单机系统,每个进程在自己的地址范围内进行运行,保证互相不干扰且协调工作。操作系统为进程之间的通信提供设施:

Unix BSD 管道pipe,命名管道named pipe软中断信号signal

Unix System V 消息message 共享存储区 shared memory 信号量semaphore

以上仅限于本机进程之间通信。

端口:网络上可以被命名和寻址的通信端口,是操作系统可以分配的一种资源,网络通信的最终地址不是主机地址,是可以描述进程的摸中标识符。TCP/IP提出协议端口porotocol port端口,表示通信进程。

       进程通过os调用绑定连接端口,而在传输层传输给该端口的数据传入进程中处理,同样在进程的数据需要传给传输层也是通过绑定端口实现。进程对端口的操作相当于对os中的i/o文件进行操作,每一个端口也对应着一个端口号,tcp/ip协议分为tcp和udp,虽然有相同port number的端口,但是互相也不冲突。 端口号的分配有全局分配,本地分配(动态分配),当进程需要访问传输层,os分配给进程一个端口号。全局分配,就是os固定分配的端口,标准的服务器都有固定的全局公认的端口号提供给服务。小于256的可以作为保留端口。

       地址:网络通信中的两台机器,可以不再同一个网络,可能间隔(网关,网桥,路由器等),所以可以分为三层寻址

机器在不同的网络则有该网络的特定id

同一个网络中的机器应该有唯一的机器id

一台机器内的进程应该有自己的唯一id

通常主机地址=网络ID+主机ID  tcp/ip中使用16位端口号来表示进程。

网络字节顺序,高价先存,tcp和udp都使用16或32整数位的高价存储,在协议的头文件中。

半相关:在网络中一个进程为协议+本地地址+端口号=三元组,也叫半相关,表示半部分。

全相关:两台机器之间通信需要使用相同协议

              协议+本地地址+本地端口号+远程地址+远程端口号 五元组 全相关。

顺序:两个连续的报文在网络中可能不会通过相同的路径到达,所以接收的顺序会和发送的顺序不一致。顺序是接收顺序与发送顺序一致。Tcp/ip提供该功能。

差错控制:检查数据差错:检查和CheckSum机制 检查连接差错:双方确认应答机制。

流控制:双方传输数据过程中,保证数据传输速率的机制,保证数据不丢失。

字节流:把传输中的报文当作一个字节序列,不提供任何数据边界。

全双工/半双工:两个方向发送或一个方向发送

缓存/带外数据:字节流服务中,没有报文边界,可以同一时刻读取任意长度的数据。为保证传输正确或流协议控制,需要使用缓存,交互型的应用程序禁用缓存。

数据传送中,希望不通过常规传输方式传送给用户以便及时处理的某一类信息(unix系统的中断键delete,Control-c)、终端流控制符Control-s、Control-q)为带外数据。

客户/服务器模式主动请求方式:

1.       打开通信通道,通知本地主机,在某一个公认地址上接收客户请求

2.       等待客户请求到达端口

3.       接收到重复服务请求,处理请求发送应答信号。接收到并发服务请求。要激活一个新进程处理客户请求,unix系统fork、exec,新进程处理客户请求,不需要对其他请求作出应答,服务完成后,关闭此进程与客户的通信链路。终止

4.       返回第二步,等待另一个客户请求。

5.       关闭服务端

客户方:

1.       打开一通信通道,并连接到服务器所在主机的特定端口。

2.       向服务器发送服务请求报文,等待并接收应答;继续提出请求…….

3.       请求结束以后关闭通信通道并终止。

1.       客户与服务器进程的作用非对称,编码不同

2.       服务进程先于客户请求而启动,系统运行,服务进程一致存在,直到正常退出或强迫退出

套接字类型:

TCP/IP的socket

Sock_stream可靠的面对连接数据传输,无差错、无重复发送,安照顺序发送接收,内设流量控制,避免数据流超限,数据为字节流,无长度限制,ftp流套接字。

Sock_DGRAM 无连接的服务,数据包以独立包的形式发送,不提供无措保证,数据可能丢失重复,发送接收的顺序混乱,网络文件系统nfs使用数据报式套接字。

Sock_Ram 接口允许较底层协议,IP,ICMP直接访问,检查新的协议实现或访问现有服务中配置的新设备。

服务端:

using System.Net;

using System.Net.Sockets;

using System.Text;

using System.Threading;

Thread mythread ;

Socket socket;

// 清理所有正在使用的资源。

        protected override void Dispose( bool disposing )

         {

              try

             {

            socket.Close();//释放资源

            mythread.Abort ( ) ;//中止线程

             }

             catch{ }

             if( disposing )

              {

                   if (components != null)

                   {

                       components.Dispose();

                   }

              }

              base.Dispose( disposing );

         }       

         public static IPAddress GetServerIP()

         {

              IPHostEntry ieh=Dns.GetHostByName(Dns.GetHostName());

              return ieh.AddressList[0];

         }

         private void BeginListen()

         {

              IPAddress ServerIp=GetServerIP();

              IPEndPoint iep=new IPEndPoint(ServerIp,8000);

              socket=new

                       Socket(AddressFamily.Inte.Network,SocketType.Stream,ProtocolType.Tcp);

              byte[] byteMessage=new byte[100]; 

              this.label1.Text=iep.ToString();

              socket.Bind(iep); 

//            do

              while(true)

              {

                   try

                   {

                       socket.Listen(5);

                       Socket newSocket=socket.Accept();

                       newSocket.Receive(byteMessage);

                       string sTime = DateTime.Now.ToShortTimeString ( ) ;

string msg=sTime+":"+"Message from:";

msg+=newSocket.RemoteEndPoint.ToString()+Encoding.Default.GetString(byteMessage);

                       this.listBox1.Items.Add(msg);

                   }

                   catch(SocketException ex)

                   {

                       this.label1.Text+=ex.ToString();

                   }

              }

//            while(byteMessage!=null);

         }

         //开始监听

         private void button1_Click(object sender, System.EventArgs e)

         {

              try

              {

                   mythread = new Thread(new ThreadStart(BeginListen));

                   mythread.Start();

              }

              catch(System.Exception er)

              {

                   MessageBox.Show(er.Message,"完成",MessageBoxButtons.OK,MessageBoxIcon.Stop);

              }

         }

客户端:

using System.Net;

using System.Net.Sockets;

using System.Text;

         private void button1_Click(object sender, System.EventArgs e)

         {

              BeginSend();      

         }

         private void BeginSend()

         {            

              string ip=this.txtip.Text;

              string port=this.txtport.Text;

              IPAddress serverIp=IPAddress.Parse(ip);           

              int serverPort=Convert.ToInt32(port);

              IPEndPoint iep=new IPEndPoint(serverIp,serverPort); 

              byte[] byteMessage; 

//            do

//            {

                   Socket socket=new Socket(AddressFamily.Inte.Network,SocketType.Stream,ProtocolType.Tcp);

                   socket.Connect(iep);

                   byteMessage=Encoding.ASCII.GetBytes(textBox1.Text);

                   socket.Send(byteMessage);

                   socket.Shutdown(SocketShutdown.Both);

                   socket.Close();

//            }

//            while(byteMessage!=null);

         }

基于TCP协议的发送和接收端

转载于:https://www.cnblogs.com/yuanermen/archive/2009/04/02/1428050.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/476348.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python delta_Python 函数

一、函数的基本语法及特性函数定义:定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可特性:减少重复代码使程序变的可扩展使程序变得易维护语法定义:#def 函数名(参数)&#xf…

浏览器返回错误汇总分析

错误代码:400 400错误是由于不正确的请求造成的,说明正在搜索的网页可能已经删除、更名或暂时不可用。 错误代码:401.1 401.1错误是由于登陆失败造成的,说明没有权限查看该目录或网页。 错误代码:401.2 401.2错误是由于…

PAT乙类1013 数素数 (20 分)

一、题目 令 P​i表示第 i 个素数。现任给两个正整数 M≤N≤10^4,请输出 PM到 PN的所有素数。输入格式: 输入在一行中给出 M 和 N,其间以空格分隔。输出格式: 输出从 P​M到 P​N的所有素数,每 10 个数字占 1 行&…

LeetCode 506. 相对名次(map)

1. 题目 给出 N 名运动员的成绩,找出他们的相对名次并授予前三名对应的奖牌。 前三名运动员将会被分别授予 “金牌”,“银牌” 和“ 铜牌”(“Gold Medal”, “Silver Medal”, “Bronze Medal”)。 (注:分数越高的选…

python docx包_[Python02] Python-docx包的使用,快速处理 Word 文件!

日常需要经常处理Word文档,发现了一个新的Python包:Python-docx,处理docx十分方便。而且这个包和pandas包结合使用,可以在word插入excel表格,节省了很多复制、粘贴、调整表格样式的时间,真的很方便&#xf…

c study_13

第十章:文件 文件文件的基本概念  所谓"文件"是指一组相关数据的有序集合。 这个数据集有一个名称,叫做文件名。 实际上在前面的各章中我们已经多次使用了文件,例如源程序文件、目标文件、可执行文件、库文件 (头文件)等。文件通常是驻留在外…

PAT乙类1014 福尔摩斯的约会 (20 分)

一、题目 大侦探福尔摩斯接到一张奇怪的字条:我们约会吧! 3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm。大侦探很快就明白了, 字条上奇怪的乱码实际上就是约会的时间星期四 14:04,因为前面两字符串中第 1 对…

LeetCode 507. 完美数

1. 题目 对于一个 正整数,如果它和除了它自身以外的所有正因子之和相等,我们称它为“完美数”。 给定一个 整数 n, 如果他是完美数,返回 True,否则返回 False 示例: 输入: 28 输出: True 解释: 28 1 2…

python分段函数图像画法_我想用Python matplotlib 画一个这样类似的图像,需要用到分段函数。大佬帮帮这个小弟?...

有做出来了import matplotlib.pyplot as pltimport numpy as npdef lin():#直线方程i0while i!80:m np.linspace(20, 100, 3)n [(80-i), (80-i), (80-i)]axes.plot(m, n)i i 20def cruve():#圆弧方程k0while k!60:if k20:r 10.0#半径a, b ((70-k) ,-20 )#圆心坐标x np.a…

python笔记(五) - 获取对象的引用

1&#xff0c;使用 getattr 函数&#xff0c;可以得到一个直到运行时才知道名称的函数的引用。 >>>li ["Larry", "Curly"]>>>li.pop<built-inmethod pop of list object at 0x00A75850>>>>getattr(li,pop)<built-inme…

spring-test dao空指针异常_014、Java异常机制

1.异常的概念和分类异常指程序运行过程中出现的非正常现象&#xff0c;例如用户输入错误、除数为零、需要处理的文件不存在、数组下标越界等。在Java的异常处理机制中&#xff0c;引进了很多用来描述和处理异常的类&#xff0c;称为异常类。异常类定义中包含了该类异常的信息和…

基于奇异值分解(SVD)的图片压缩实践

文章目录1. 前言2. 原理简介2.1 SVD定义3. 实践代码4. 参考文献1. 前言 数字图片在计算机中是以矩阵形式存储的。所以可以通过矩阵理论和矩阵算法对数字图像进行分析和处理。本文通过对图片进行SVD压缩&#xff0c;对不同的参数下的压缩效果进行对比。 SVD概念可以参考&#…

执行文件异常报错:ImportError: attempted relative import with no known parent package

问题描述 1. 源代码中的导入代码&#xff1a; from ..utils.osutils import mkdir_if_missing #导入自己的 函数 from ..utils.serialization import write_json, read_json这个是将utils中的py文件导入到cuhk03中。但是报错&#xff01; 解决方法 1. 相对导入 其中上述…

待机、休眠、睡眠的区别和优缺点

Windows操作系统中很早就加入了待机、休眠等模式&#xff0c;而Windows Vista中更是新加入了一种叫做睡眠的模式&#xff0c;可是很多人还是习惯在不使用电脑的时候将其彻底关闭。其实充分利用这些模式&#xff0c;我们不仅可以节约电力消耗&#xff0c;还可以用尽可能短的时间…

LeetCode 508. 出现次数最多的子树元素和(递归)

1. 题目 给你一个二叉树的根结点&#xff0c;请你找出出现次数最多的子树元素和。 一个结点的「子树元素和」定义为以该结点为根的二叉树上所有结点的元素之和&#xff08;包括结点本身&#xff09;。 你需要返回出现次数最多的子树元素和。如果有多个元素出现的次数相同&…

知识图谱入门视频(一)

学习内容&#xff1a; 知识图谱导论 陈华钧 浙江大学计算机科学与技术学院 教授 小象学院 哔哩哔哩 第一章 【其实后面的方法学习只是一个框架式的学习&#xff0c;并不明白具体的操作】 1. 什么是知识图谱&#xff1f; 知识图谱是一个系统&#xff01; 从根据场景构建再到场…

onenetsim定位功能吗_经常玩手机的抓紧看看,原来手机键盘还隐藏4个实用功能,真实用...

可爱的人都关注我了&#xff0c;就差你了1在日常生活中&#xff0c;大家对手机的依赖性越来越大&#xff0c;不管走到哪&#xff0c;时时刻刻都拿着手机发信息。可是&#xff0c;用了这么久的手机&#xff0c;你真的会用手机键盘吗&#xff1f;你知道手机键盘上隐藏的小功能吗&…

程序模拟键盘鼠标操作

用代码模拟键盘鼠标操作,主要用到keybd_event/mouse_event或者SendInput API函数.使用示例如下(附注释): /** 模拟键盘输入,以按窗口键(WIN键)为例 *///keybd_event模拟键盘输入示例::keybd_event( VK_LWIN, 0, 0, 0); //按下WIN键 ::keybd_event( VK_LW…

LeetCode 520. 检测大写字母

1. 题目 给定一个单词&#xff0c;你需要判断单词的大写使用是否正确。 我们定义&#xff0c;在以下情况时&#xff0c;单词的大写用法是正确的&#xff1a; 全部字母都是大写&#xff0c;比如"USA"。 单词中所有字母都不是大写&#xff0c;比如"leetcode&qu…

不同电脑 命名管道_电脑键盘上的F1到F12,这些键都有哪些用处?用了5年总算明白了...

电脑键盘上的F1到F12&#xff0c;这些键都有哪些用处&#xff0c;用了5年总算明白了经常使用电脑的朋友会发现&#xff0c;电脑键盘上有一排F开头的键。那么这些键到底有什么用处呢&#xff1f;下面我们一起来了解一下。首先这些键都属于快捷键&#xff0c;所以每个键都有不同的…