socket的应用场景,在快速,稳定,保持长连接的数据传输代码。Http也是socket封装出来的,基于一次请求一次回复,然后断开的socket连接封装。
比如我们常见的游戏服务器,目前的很火的物联网服务器,都需要开启socket服务器去监听实时传输的数据。
那么我们如何实现socket的监听呢。说到这里,我们需要知道,socket的监听分为tcp和udp两种形式,但是tcp其实是udp封装而来的,可看做可靠的udp传输,基于udp的定向传输,收到消息回复发送方收到消息。等验证,来实现tcp的数据传输,所以一般我们tcp的传输相对udp稍微慢一点。
我们先将一下socket 的tcp状态创建一个TCPListener类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
/// <summary>
/// 建立TCP通信监听服务
/// </summary>
internal
class
TCPListener
{
private
IPEndPoint _IP;
private
Socket _Listeners;
private
volatile
bool
IsInit =
false
;
private
List<TSocketBase> sockets =
new
List<TSocketBase>();
/// <summary>
/// 初始化服务器
/// </summary>
public
TCPListener(
string
ip =
"0.0.0.0"
,
int
port = 9527)
{
IsInit =
true
;
IPEndPoint localEP =
new
IPEndPoint(IPAddress.Parse(ip), port);
this
._IP = localEP;
try
{
Console.WriteLine(
string
.Format(
"Listen Tcp -> {0}:{1} "
, ip, port));
this
._Listeners =
new
Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this
._Listeners.Bind(
this
._IP);
this
._Listeners.Listen(5000);
SocketAsyncEventArgs sea =
new
SocketAsyncEventArgs();
sea.Completed +=
new
EventHandler<SocketAsyncEventArgs>(
this
.AcceptAsync_Async);
this
.AcceptAsync(sea);
}
catch
(Exception ex)
{
Console.WriteLine(ex);
this
.Dispose();
}
}
private
void
AcceptAsync(SocketAsyncEventArgs sae)
{
if
(IsInit)
{
if
(!
this
._Listeners.AcceptAsync(sae))
{
AcceptAsync_Async(
this
, sae);
}
}
else
{
if
(sae !=
null
)
{
sae.Dispose();
}
}
}
private
void
AcceptAsync_Async(
object
sender, SocketAsyncEventArgs sae)
{
if
(sae.SocketError == SocketError.Success)
{
var
socket =
new
TSocketClient(sae.AcceptSocket);
sockets.Add(socket);
Console.WriteLine(
"Remote Socket LocalEndPoint:"
+ sae.AcceptSocket.LocalEndPoint +
" RemoteEndPoint:"
+
sae.AcceptSocket.RemoteEndPoint.ToString());
}
sae.AcceptSocket =
null
;
if
(IsInit)
{
this
._Listeners.AcceptAsync(sae);
}
else
{
sae.Dispose();
}
}
/// <summary>
/// 释放资源
/// </summary>
public
void
Dispose()
{
if
(IsInit)
{
IsInit =
false
;
this
.Dispose(
true
);
GC.SuppressFinalize(
this
);
}
}
/// <summary>
/// 释放所占用的资源
/// </summary>
/// <param name="flag1"></param>
protected
virtual
void
Dispose([MarshalAs(UnmanagedType.U1)]
bool
flag1)
{
if
(flag1)
{
if
(_Listeners !=
null
)
{
try
{
Console.WriteLine(
string
.Format(
"Stop Listener Tcp -> {0}:{1} "
,
this
.IP.Address.ToString(),
this
.IP.Port));
_Listeners.Close();
_Listeners.Dispose();
}
catch
{
}
}
}
}
/// <summary>
/// 获取绑定终结点
/// </summary>
public
IPEndPoint IP
{
get
{
return
this
._IP; }
}
}
|
主要两点我们socket的初始化代码 new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);初始化的类型是基于tcp。
还有就是我们绑定ip地址,过去很多人socket的bind地址习惯写成127.0.0.1(测试环境)或者读取网卡信息,读取ip地址,这样麻烦,代码要写很多,切不符合多网卡多线路实际环境。我们用0.0.0.0是表示开启ipv4的所有线路监听,包括你的多路网卡,以及127.0.0.1
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 TCPListener tcp = new TCPListener(); 6 Console.ReadLine(); 7 } 8 }
我们运行看一下效果
接下来我们使用telnet测试一下
开启telnet
然后打开cmd
输入 telnet 127.0.0.1 9527
我们看到收到了一个连接
本文转自左正博客园博客,原文链接:http://www.cnblogs.com/soundcode/p/7238610.html/,如需转载请自行联系原作者