C# Socket网络编程精华篇(转)

我们在讲解Socket编程前,先看几个和Socket编程紧密相关的概念:

  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):又称为物理数据网络接口层,负责报文传输。

然后我们来看下tcp层次模型图

从上图中可以看出,应用程序在应用层运行,在传输层,在数据前加上了TCP头,在

网络层加上的IP头,在数据链路层加上了帧。

2,端口

端口号范围:0-65535,总共能表示65536个数。

   按端口号可分为3大类

  (1)公认端口(WellKnownPorts):从0到1023,它们紧密绑定(binding)于一些服务。通常这些端口的通讯明确表明了某种服务的协议。例如:80端口实际上总是HTTP通讯。

  (2)注册端口(RegisteredPorts):从1024到49151。它们松散地绑定于一些服务。也就是说有许多服务绑定于这些端口,这些端口同样用于许多其它目的。例如:许多系统处理动态端口从1024左右开始。

  (3)动态和/或私有端口(Dynamicand/orPrivatePorts):从49152到65535。理论上,不应为服务分配这些端口。实际上,机器通常从1024起分配动态端口。

3.TCP和UDP报文

下面一起来看下TCP和UDP的报文图

从图中我们可以看出TCP和UDP中都有校验和,但是在UDP报文中,一般不使用校验和,这样可以加快数据传输的速度,但是数据的准确性可能会受到影响。换句话说,Tcp协议都有校验和,为了保证传输数据的准确性。

3.Socket

Socket包括Ip地址和端口号两部分,程序通过Socket来通信,Socket相当于操作系统的一个组件。Socket作为进程之间通信机制,通常也称作”套接字”,用于描述IP地址和端口号,是一个通信链的句柄。说白了,就是两个程序通信用的。

生活案例对比:

Socket之间的通信可以类比生活中打电话的案例。任何用户在通话之前,首先要占有一部电话机,相当于申请一个Socket,同时要知道对方的号码,相当于对方有一个固定的Socket,然后向对方拨号呼叫,相当于发出连接请求。假如对方在场并空闲,拿起 电话话筒,双方就可以进行通话了。双方的通话过程,是一方向电话机发出信号和对方从电话机接收信号的过程,相当于向socket发送数据和从socket接收数据。通话结束后,一方挂起电话机,相当于关闭socket,撤销连接。

注意:Socket不仅可以在两台电脑之间通信,还可以在同一台电脑上的两个程序间通信。

4,端口进阶(深入)

通过IP地址确定了网络中的一台电脑后,该电脑上可能提供很多提供服务的应用,每一个应用都对应一个端口。

在Internet上有很多这样的主机,这些主机一般运行了多个服务软件 ,同时提供几种服务,每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务(应用程序)

例如:http 使用80端口,   ftp使用21端口     smtp使用25端口

5.Socket分类

Socket主要有两种类型:

  1. 流式Socket

是一种面向连接的Socket,针对于面向连接的TCP服务应用,安全,但是效率低

2,数据报式Socket

是一种无连接的Socket,对应于无连接的UDP服务应用,不安全,但效率高

6. Socket一般应用模式(服务器端和客户端)

服务器端的Socket(至少需要两个)

01.一个负责接收客户端连接请求(但不负责与客户端通信)

02.每成功接收到客户端的连接便在服务器端产生一个对应的复杂通信的Socket

021.在接收到客户端连接时创建

022. 为每个连接成功的客户端请求在服务器端都创建一个对应的Socket(负责和客户端通信)

客户端的Socket

  1. 必须指定要连接的服务器地址和端口

  2. 通过创建一个Socket对象来初始化一个到服务器端的TCP连接

通过上图,我们可以看出,首先服务器会创建一个负责监听的socket,然后客户端通过socket连接到服务器指定端口,最后服务器端负责监听的socket,监听到客户端有连接过来了,就创建一个负责和客户端通信的socket。

下面我们来看下Socket更具体的通信过程:

Socket的通讯过程

服务器端:

01,申请一个socket

02,绑定到一个IP地址和一个端口上

03,开启侦听,等待接收连接

客户端:

01,申请一个socket

02,连接服务器(指明IP地址和端口号)

服务器端接收到连接请求后,产生一个新的socket(端口大于1024)与客户端建立连接并进行通信,原监听socket继续监听。

注意:负责通信的Socket不能无限创建,创建的数量和操作系统有关。

7.Socket的构造函数

Public Socket(AddressFamily addressFamily,SocketType  socketType,ProtocolType  protocolTYpe)

AddressFamily:指定Socket用来解析地址的寻址方案。例如:InterNetWork指示当Socket使用一个IP版本4地址连接

SocketType:定义要打开的Socket的类型

Socket类使用ProtocolType枚举向Windows  Sockets  API通知所请求的协议

注意:

1,端口号必须在 1 和 65535之间,最好在1024以后。

2,要连接的远程主机必须正在监听指定端口,也就是说你无法随意连接远程主机。

如:

IPAddress addr = IPAddress.Parse("127.0.0.1");

IPEndPoint endp = new IPEndPoint(addr,,9000);

服务端先绑定:serverWelcomeSocket.Bind(endp)

客户端再连接:clientSocket.Connect(endp)

3,一个Socket一次只能连接一台主机

4,Socket关闭后无法再次使用

5,每个Socket对象只能与一台远程主机连接。如果你想连接到多台远程主机,你必须创建多个Socket对象。

8.Socket常用类和方法

相关类:

IPAddress:包含了一个IP地址

IPEndPoint:包含了一对IP地址和端口号

方法:

Socket():创建一个Socket

Bind():绑定一个本地的IP和端口号(IPEndPoint)

Listen():让Socket侦听传入的连接吃那个病,并指定侦听队列容量

Connect():初始化与另一个Socket的连接

Accept():接收连接并返回一个新的Socket

Send():输出数据到Socket

Receive():从Socket中读取数据

Close():关闭Socket,销毁连接

接下来,我们同一个简单的服务器和客户端通信的案例,来看下Sokcet的具体用法,效果图如下:


关键代码:

服务器端代码:

private void Form1_Load(object sender, EventArgs e)

 

        {

 

            Control.CheckForIllegalCrossThreadCalls = false;

 

        }

 

 

 

        private void btnListen_Click(object sender, EventArgs e)

 

        {

 

            //ip地址

 

            IPAddress ip = IPAddress.Parse(txtIP.Text);

 

           // IPAddress ip = IPAddress.Any;

 

            //端口号

 

            IPEndPoint point=new IPEndPoint(ip,int.Parse(txtPort.Text));

 

            //创建监听用的Socket

 

            /*


             * AddressFamily.InterNetWork:使用 IP4地址。


SocketType.Stream:支持可靠、双向、基于连接的字节流,而不重复数据。此类型的 Socket 与单个对方主机进行通信,并且在通信开始之前需要远程主机连接。Stream 使用传输控制协议 (Tcp) ProtocolType 和 InterNetworkAddressFamily。


ProtocolType.Tcp:使用传输控制协议。


             */

 

            //使用IPv4地址,流式socket方式,tcp协议传递数据

 

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

 

            //创建好socket后,必须告诉socket绑定的IP地址和端口号。

 

            //让socket监听point

 

            try

 

            {

 

                //socket监听哪个端口

 

                socket.Bind(point);

 

                //同一个时间点过来10个客户端,排队

 

                socket.Listen(10);

 

                ShowMsg("服务器开始监听");

 

                Thread thread = new Thread(AcceptInfo);

 

                thread.IsBackground = true;

 

                thread.Start(socket);

 

            }

 

            catch (Exception ex)

 

            {

 

               

 

               ShowMsg(ex.Message);

 

            }

 

        }

 

        //记录通信用的Socket

 

        Dictionary<string,Socket> dic=new Dictionary<string, Socket>();

 

       // private Socket client;

 

        void AcceptInfo(object o)

 

        {

 

            Socket socket = o as Socket;

 

            while (true)

 

            {

 

                //通信用socket

 

                try

 

                {

 

                    //创建通信用的Socket

 

                  Socket  tSocket = socket.Accept();

 

                  string point = tSocket.RemoteEndPoint.ToString();

 

                    //IPEndPoint endPoint = (IPEndPoint)client.RemoteEndPoint;

 

                    //string me = Dns.GetHostName();//得到本机名称

 

                    //MessageBox.Show(me);

 

                 ShowMsg(point + "连接成功!");

 

                 cboIpPort.Items.Add(point);

 

                 dic.Add(point, tSocket);

 

                    //接收消息

 

                    Thread th = new Thread(ReceiveMsg);

 

                    th.IsBackground = true;

 

                    th.Start(tSocket);

 

                }

 

                catch (Exception ex)

 

                {

 

                    ShowMsg(ex.Message);

 

                    break;

 

                }

 

            }

 

        }

 

        //接收消息

 

        void ReceiveMsg(object o)

 

        {

 

            Socket client = o as Socket;

 

            while (true)

 

            {

 

                //接收客户端发送过来的数据

 

                try

 

                {

 

                    //定义byte数组存放从客户端接收过来的数据

 

                    byte[] buffer = new byte[1024 * 1024];

 

                    //将接收过来的数据放到buffer中,并返回实际接受数据的长度

 

                    int n = client.Receive(buffer);

 

                    //将字节转换成字符串

 

                    string words = Encoding.UTF8.GetString(buffer, 0, n);

 

                  

 

                    ShowMsg(client.RemoteEndPoint.ToString() + ":" + words);

 

                }

 

                catch (Exception ex)

 

                {

 

                   ShowMsg(ex.Message);

 

                    break;

 

                }

 

            }

 

        }

 

 

 

        void ShowMsg(string msg)

 

        {

 

            txtLog.AppendText(msg+"\r\n");

 

        }

 

 

 

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)

 

        {

 

            //主窗体关闭时关闭子线程

 

          

 

        }

 

        //给客户端发送消息

 

        private void btnSend_Click(object sender, EventArgs e)

 

        {

 

            try

 

            {

 

                ShowMsg(txtMsg.Text);

 

                string ip = cboIpPort.Text;

 

                byte[] buffer = Encoding.UTF8.GetBytes(txtMsg.Text);

 

                dic[ip].Send(buffer);

 

                // client.Send(buffer);

 

            }

 

            catch (Exception ex)

 

            {

 

               ShowMsg(ex.Message);

 

            }

 

 

 

        }

客户端代码:

Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 

        private void btnConnection_Click(object sender, EventArgs e)

 

        {

 

            //连接到的目标IP

 

            IPAddress ip = IPAddress.Parse(txtIP.Text);

 

            //IPAddress ip = IPAddress.Any;

 

            //连接到目标IP的哪个应用(端口号!)

 

            IPEndPoint point=new IPEndPoint(ip,int.Parse(txtPort.Text));

 

            try

 

            {

 

                //连接到服务器

 

                client.Connect(point);

 

                ShowMsg("连接成功");

 

                ShowMsg("服务器" + client.RemoteEndPoint.ToString());

 

                ShowMsg("客户端:" + client.LocalEndPoint.ToString());

 

                //连接成功后,就可以接收服务器发送的信息了

 

                Thread th=new Thread(ReceiveMsg);

 

                th.IsBackground = true;

 

                th.Start();

 

            }

 

            catch (Exception ex)

 

            {

 

                ShowMsg(ex.Message);

 

            }

 

        }

 

        //接收服务器的消息

 

        void ReceiveMsg()

 

        {

 

            while (true)

 

            {

 

                try

 

                {

 

                    byte[] buffer = new byte[1024 * 1024];

 

                    int n = client.Receive(buffer);

 

                    string s = Encoding.UTF8.GetString(buffer, 0, n);

 

                    ShowMsg(client.RemoteEndPoint.ToString() + ":" + s);

 

                }

 

                catch (Exception ex)

 

                {

 

                    ShowMsg(ex.Message);

 

                    break;

 

                }

 

            }

 

          

 

        }

 

 

 

        void ShowMsg(string msg)

 

        {

 

            txtInfo.AppendText(msg+"\r\n");

 

        }

 

 

 

        private void btnSend_Click(object sender, EventArgs e)

 

        {

 

            //客户端给服务器发消息

 

            if (client!=null)

 

            {

 

                try

 

                {

 

                   ShowMsg(txtMsg.Text);

 

                    byte[] buffer = Encoding.UTF8.GetBytes(txtMsg.Text);

 

                    client.Send(buffer);

 

                }

 

                catch (Exception ex)

 

                {

 

                   ShowMsg(ex.Message);

 

                }

 

            }

 

           

 

        }

 

 

 

        private void ClientForm_Load(object sender, EventArgs e)

 

        {

 

            Control.CheckForIllegalCrossThreadCalls = false;

 

        }

好了,到这里我们对Socket的讨论就告一个段落了。

时间: 2024-11-08 20:30:24

C# Socket网络编程精华篇(转)的相关文章

C# Socket网络编程精华篇

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

socket网络编程——操作篇

一.问题思考 问1.网络通信应用在什么场合?通信的前提是什么? 答1.主要应用在不同主机进程间的互相通信,同一主机的进程也可以使用网络进行通信.通信的前提是如何标识通信进程的唯一,由于不同主机的进程极有可能具有相同的PID,因此,在网络中单单靠PID是无法准确进行标识进程身份的,TCP/IP协议族网络层的IP地址可以唯一的标识连入网络的主机. 问2.socket编程重点是什么? 答2.掌握基于TCP.UDP的S/C架构的编程要点:掌握网络通信方式之间的区别和应用场合. 问3.什么是网络模型? 答

python_day8 socket 网络编程 基本篇

服务端: server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)server.bind(('127.0.0.1',80))server.listen(5)conn,address=server.accept()data=conn.recv(1024)print(data)conn.send(data.upper())conn.close()server.close() 客户端 import socketclient=socket.socke

Socket网络编程(TCP/IP/端口/类)和实例

Socket网络编程(TCP/IP/端口/类)和实例 原文:C# Socket网络编程精华篇 转自:微冷的雨 我们在讲解Socket编程前,先看几个和Socket编程紧密相关的概念: TCP/IP层次模型 当然这里我们只讨论重要的四层 01,应用层(Application):应用层是个很广泛的概念,有一些基本相同的系统级TCP/IP应用以及应用协议,也有许多的企业应用和互联网应用.http协议在应用层运行. 02,传输层(Tanspot):传输层包括UDP和TCP,UDP几乎不对报文进行检查,而

Java基础篇Socket网络编程中的应用实例

说到java网络通讯章节的内容,刚入门的学员可能会感到比较头疼,应为Socket通信中一定会伴随有IO流的操作,当然对IO流比较熟练的哥们会觉得这是比较好玩的一章,因为一切都在他们的掌握之中,这样操作起来就显得非常得心应手,但是对于IO本来就不是多熟悉的哥们来说就有一定的困难了,在搞清楚IO流操作机制的同时还必须会应用到Socket通信中去,否则会对得到的结果感到非常郁闷和懊恼,下面就和大家一起分享一下自己遇到一点小麻烦后的感触以及给出的解决办法. 要求:客户端通过Socket通信技术上传本地一

Python之路【第九篇】:Python基础(25)——socket网络编程

socket网络编程 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,对于文件用打开.读写.关闭模式来操作.socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO.打开.关闭) socket和file的区别: file模块是针对某个指定

socket 网络编程快速入门(一)教你编写基于UDP/TCP的服务(客户端)通信

因为UNIX和Win的socket大同小异,为了方便和大众化,这里先介绍Winsock编程. socket 网络编程的难点在入门的时候就是对基本函数的了解和使用,因为这些函数的结构往往比较复杂,参数大部分都是结构体,令人难以记忆和理解. 但是一旦我们知道这些函数包括其参数的具体含义,socket网络编程也就变得不是那么复杂.这里不赘述 具体函数的详细含义,网络上有很多的文章,同时笔者建议大家参考 MSDN,对返回值,参数等会有更好的理解. 以下均为单线程的简单实例,多线程的请关注下一篇文章. (

网络版shell之网络编程练习篇--telnet服务端

网络版shell之网络编程练习篇--telnet服务端 以前写过一个shell命令解释器,对与shell命令解释器的执行流程有了清晰的认识,这段时间学习网络编程,至于网络编程的细节以及知识点,已经在上 一遍博客中,转载了从网上摘的文章,基本概括了网络编程的主要api,而对于程序员,更重要的是解决实际问题的能力,所以练习是非常重要的,现在,我们在 一起shell命令解释器的基础上,写一个基于socket网络编程的网络版shell命令解释器,也可以称之为telnet服务端.  telnet服务端代码

《C#网络编程高级篇之网页游戏辅助程序设计(扫描版)》

<C#网络编程高级篇之网页游戏辅助程序设计>通过编写C#网络编程语言中具有代表性的实例,向读者深入细致地讲解了如何利用C#语言进行网页游戏辅助程序设计.本书通过大量的代码引导读者一步步学习和掌握C#的网络应用编程的方法和网页游戏辅助程序的设计技术. <C#网络编程高级篇之网页游戏辅助程序设计>涉及的领域包括多线程编程技术.socket套接字编程.tcp协议编程.http协议编程.远程控制技术.木马技术.模拟键盘和鼠标技术.网页游戏辅助程序设计技术等. <C#网络编程高级篇之网