最近在研究socket,今天看到很好的一篇关于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主要有两种类型:

流式Socket

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

2,数据报式Socket

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

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

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

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

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

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

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

客户端的Socket

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

通过创建一个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的具体用法,效果图如下:

关键代码:

服务器端代码:

1 private void Form1_Load(object sender, EventArgs e)

  2
3 {
4
5 Control.CheckForIllegalCrossThreadCalls = false;
6
7 }
8
9
10
11 private void btnListen_Click(object sender, EventArgs e)
12
13 {
14
15 //ip地址
16
17 IPAddress ip = IPAddress.Parse(txtIP.Text);
18
19 // IPAddress ip = IPAddress.Any;
20
21 //端口号
22
23 IPEndPoint point=new IPEndPoint(ip,int.Parse(txtPort.Text));
24
25 //创建监听用的Socket
26
27 /*
28
29 * AddressFamily.InterNetWork:使用 IP4地址。
30
31 SocketType.Stream:支持可靠、双向、基于连接的字节流,而不重复数据。此类型的 Socket 与单个对方主机进行通信,并且在通信开始之前需要远程主机连接。Stream 使用传输控制协议 (Tcp) ProtocolType 和 InterNetworkAddressFamily。
32
33 ProtocolType.Tcp:使用传输控制协议。
34
35 */
36
37 //使用IPv4地址,流式socket方式,tcp协议传递数据
38
39 Socket socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
40
41 //创建好socket后,必须告诉socket绑定的IP地址和端口号。
42
43 //让socket监听point
44
45 try
46
47 {
48
49 //socket监听哪个端口
50
51 socket.Bind(point);
52
53 //同一个时间点过来10个客户端,排队
54
55 socket.Listen(10);
56
57 ShowMsg("服务器开始监听");
58
59 Thread thread = new Thread(AcceptInfo);
60
61 thread.IsBackground = true;
62
63 thread.Start(socket);
64
65 }
66
67 catch (Exception ex)
68
69 {
70
71
72
73 ShowMsg(ex.Message);
74
75 }
76
77 }
78
79 //记录通信用的Socket
80
81 Dictionary<string,Socket> dic=new Dictionary<string, Socket>();
82
83 // private Socket client;
84
85 void AcceptInfo(object o)
86
87 {
88
89 Socket socket = o as Socket;
90
91 while (true)
92
93 {
94
95 //通信用socket
96
97 try
98
99 {
100
101 //创建通信用的Socket
102
103 Socket tSocket = socket.Accept();
104
105 string point = tSocket.RemoteEndPoint.ToString();
106
107 //IPEndPoint endPoint = (IPEndPoint)client.RemoteEndPoint;
108
109 //string me = Dns.GetHostName();//得到本机名称
110
111 //MessageBox.Show(me);
112
113 ShowMsg(point + "连接成功!");
114
115 cboIpPort.Items.Add(point);
116
117 dic.Add(point, tSocket);
118
119 //接收消息
120
121 Thread th = new Thread(ReceiveMsg);
122
123 th.IsBackground = true;
124
125 th.Start(tSocket);
126
127 }
128
129 catch (Exception ex)
130
131 {
132
133 ShowMsg(ex.Message);
134
135 break;
136
137 }
138
139 }
140
141 }
142
143 //接收消息
144
145 void ReceiveMsg(object o)
146
147 {
148
149 Socket client = o as Socket;
150
151 while (true)
152
153 {
154
155 //接收客户端发送过来的数据
156
157 try
158
159 {
160
161 //定义byte数组存放从客户端接收过来的数据
162
163 byte[] buffer = new byte[1024 * 1024];
164
165 //将接收过来的数据放到buffer中,并返回实际接受数据的长度
166
167 int n = client.Receive(buffer);
168
169 //将字节转换成字符串
170
171 string words = Encoding.UTF8.GetString(buffer, 0, n);
172
173
174
175 ShowMsg(client.RemoteEndPoint.ToString() + ":" + words);
176
177 }
178
179 catch (Exception ex)
180
181 {
182
183 ShowMsg(ex.Message);
184
185 break;
186
187 }
188
189 }
190
191 }
192
193
194
195 void ShowMsg(string msg)
196
197 {
198
199 txtLog.AppendText(msg+"\r\n");
200
201 }
202
203
204
205 private void Form1_FormClosing(object sender, FormClosingEventArgs e)
206
207 {
208
209 //主窗体关闭时关闭子线程
210
211
212
213 }
214
215 //给客户端发送消息
216
217 private void btnSend_Click(object sender, EventArgs e)
218
219 {
220
221 try
222
223 {
224
225 ShowMsg(txtMsg.Text);
226
227 string ip = cboIpPort.Text;
228
229 byte[] buffer = Encoding.UTF8.GetBytes(txtMsg.Text);
230
231 dic[ip].Send(buffer);
232
233 // client.Send(buffer);
234
235 }
236
237 catch (Exception ex)
238
239 {
240
241 ShowMsg(ex.Message);
242
243 }
244
245
246
247 }

客户端代码:

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

  2
3 private void btnConnection_Click(object sender, EventArgs e)
4
5 {
6
7 //连接到的目标IP
8
9 IPAddress ip = IPAddress.Parse(txtIP.Text);
10
11 //IPAddress ip = IPAddress.Any;
12
13 //连接到目标IP的哪个应用(端口号!)
14
15 IPEndPoint point=new IPEndPoint(ip,int.Parse(txtPort.Text));
16
17 try
18
19 {
20
21 //连接到服务器
22
23 client.Connect(point);
24
25 ShowMsg("连接成功");
26
27 ShowMsg("服务器" + client.RemoteEndPoint.ToString());
28
29 ShowMsg("客户端:" + client.LocalEndPoint.ToString());
30
31 //连接成功后,就可以接收服务器发送的信息了
32
33 Thread th=new Thread(ReceiveMsg);
34
35 th.IsBackground = true;
36
37 th.Start();
38
39 }
40
41 catch (Exception ex)
42
43 {
44
45 ShowMsg(ex.Message);
46
47 }
48
49 }
50
51 //接收服务器的消息
52
53 void ReceiveMsg()
54
55 {
56
57 while (true)
58
59 {
60
61 try
62
63 {
64
65 byte[] buffer = new byte[1024 * 1024];
66
67 int n = client.Receive(buffer);
68
69 string s = Encoding.UTF8.GetString(buffer, 0, n);
70
71 ShowMsg(client.RemoteEndPoint.ToString() + ":" + s);
72
73 }
74
75 catch (Exception ex)
76
77 {
78
79 ShowMsg(ex.Message);
80
81 break;
82
83 }
84
85 }
86
87
88
89 }
90
91
92
93 void ShowMsg(string msg)
94
95 {
96
97 txtInfo.AppendText(msg+"\r\n");
98
99 }
100
101
102
103 private void btnSend_Click(object sender, EventArgs e)
104
105 {
106
107 //客户端给服务器发消息
108
109 if (client!=null)
110
111 {
112
113 try
114
115 {
116
117 ShowMsg(txtMsg.Text);
118
119 byte[] buffer = Encoding.UTF8.GetBytes(txtMsg.Text);
120
121 client.Send(buffer);
122
123 }
124
125 catch (Exception ex)
126
127 {
128
129 ShowMsg(ex.Message);
130
131 }
132
133 }
134
135
136
137 }
138
139
140
141 private void ClientForm_Load(object sender, EventArgs e)
142
143 {
144
145 Control.CheckForIllegalCrossThreadCalls = false;
146
147 }
文章来源http://www.cr173.com/html/19555_1.html

C# socket通信的更多相关文章

  1. 我看不下去鸟。。。。Java和C#的socket通信真的简单吗?

    这几天在博客园上看到好几个写Java和C#的socket通信的帖子.但是都为指出其中关键点. C# socket通信组件有很多,在vs 使用nuget搜索socket组件有很多类似的.本人使用的是自己 ...

  2. php简单实现socket通信

    socket通信的原理在这里就不说了,它的用途还是比较广泛的,我们可以使用socket来做一个API接口出来,也可以使用socket来实现两个程序之间的通信,我们来研究一下在php里面如何实现sock ...

  3. Socket通信类

    package com.imooc; import java.io.BufferedReader; import java.io.IOException; import java.io.InputSt ...

  4. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-介绍

    一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...

  5. socket通信

    socket通信 一:socket基于Tcp连接,数据传输有保证 二:socket连接的建立过程: 1:服务器监听 2:客户端发出请求 3:建立连接 4:通信 三:一个简单的例子:服务器端每隔一段时间 ...

  6. Android之Socket通信、List加载更多、Spinner下拉列表

    Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务 ...

  7. .NET开源高性能Socket通信中间件Helios介绍及演示

    一:Helios是什么 Helios是一套高性能的Socket通信中间件,使用C#编写.Helios的开发受到Netty的启发,使用非阻塞的事件驱动模型架构来实现高并发高吞吐量.Helios为我们大大 ...

  8. iOS开发之Socket通信实战--Request请求数据包编码模块

    实际上在iOS很多应用开发中,大部分用的网络通信都是http/https协议,除非有特殊的需求会用到Socket网络协议进行网络数 据传输,这时候在iOS客户端就需要很好的第三方CocoaAsyncS ...

  9. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-简单例子-实现简单的服务端客户端消息应答

    一.AgileEAS.NET SOA中间件Socket/Tcp框架介绍 在文章AgileEAS.NET SOA 中间件平台Socket/Tcp通信框架介绍一文之中我们对AgileEAS.NET SOA ...

  10. AgileEAS.NET SOA 中间件平台.Net Socket通信框架-完整应用例子-在线聊天室系统-下载配置

    一.AgileEAS.NET SOA中间件Socket/Tcp框架介绍 在文章AgileEAS.NET SOA 中间件平台Socket/Tcp通信框架介绍一文之中我们对AgileEAS.NET SOA ...

随机推荐

  1. python 反射器

    #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ @author: zengchunyun ""& ...

  2. 网站开发常用cmd命令

    一.Windows服务安装: framework 4.0 : cd C:\Windows\Microsoft.NET\Framework\v4.0.30319 framework 2.0 :  cd ...

  3. Linux安装软件总结(二.几种安装命令介绍)

    一.rpm包安装方式步骤: 1.找到相应的软件包,比如soft.version.rpm,下载到本机某个目录: 2.打开一个终端,su -成root用户: 3.cd soft.version.rpm所在 ...

  4. JVM内存区域异常分析

    在Java虚拟机规范描述中,除程序计数器外,其他几个运行时区域都有可能发生OutOfMemoryError异常.接下来将对各区域分别进行分析介绍,内容包括触发各区域OutOfMemoryError异常 ...

  5. MySQL Cluster搭建与测试

    MySQL Cluster是一个基于NDB Cluster存储引擎的完整的分布式数据库系统.不仅仅具有高可用性,而且可以自动切分数据,冗余数据等高级功能.和Oracle Real Cluster Ap ...

  6. 安卓中級教程(4):ScrollView與ListView之間的高度問題

    在scrollView中加插ListView是一個大難題.其中一個難題是Listview的高度難以計算,輸出效果往往強差人意,就讓我們看看當中的問題 . <LinearLayout xmlns: ...

  7. finally类

    finally叫做最后的执行快,什么是最后的执行快?他的意思是这样的 他是写在try catch 的后面但是只能写一个,他设计这个finally的意思就是,如果try里面出错肯定会往陷阱里 面跑.没有 ...

  8. linux-系统调用

    p { margin-bottom: 0.1in; line-height: 120% } ● Fork() 创建子进程. 创建单个子进程: pid_t pid; pid = fork(); if(p ...

  9. ADO.Net读取器获取数据库数据

    string str = Configuration.ConfigurationManager.AppSettings[str].ToString(); string sql = "sele ...

  10. 关于C#使用Dllimport 导入vc++动态库后网站部署提示 “无法加载 DLL,找不到指定模块”的解决方法。

    这次项目需要,做了一个C#写的WebService服务给外部调用,服务内部引用了算法库,本地调试已经通过,现场部署服务时各种提示找不到DLL文件. 第一.如果是包含有32位库在64位服务器系统上运行, ...