socket编程实例

  • 格式:pdf
  • 大小:151.31 KB
  • 文档页数:6

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 dic=new Dictionary();

// 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);