-
Notifications
You must be signed in to change notification settings - Fork 3
/
multiThreadServer.tcl
130 lines (107 loc) · 7.94 KB
/
multiThreadServer.tcl
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
119
120
121
122
123
124
125
126
127
128
129
# Серверная компонента
# ��������� ���������� �������
# импортируем библиотеку потоков
package require Thread
# ��������� ��������� �� 7000 tcp �����
# ��� ��������� ������� �� �������, ����� ����������� ��������� _Accept
# открываем порт на входящие запросы
socket -server _Accept 7000
# ������ � ���������� tcl �������
# ��� ������ ������, ��� �� tcl-���������� ����������.
# ��� Tk-���������� ������ ������ �� �����.
# время ожидания - пока работает скрипт
vwait forever
# ���������� ���������� �����
# � ���� 5 ����� ������� ������������ ������� �� 400-�� ��������
set Main(TcpPool,maxjobs) 5
# ������� ��� ������� �� ���� �����
set Main(tcptpid) [tpool::create -minworkers $Main(TcpPool,maxjobs) -maxworkers $Main(TcpPool,maxjobs)) -initcmd {
# �������������� ����������, �������� ���������� �������� �����
tsv::set TcpTpool CountJobs 0
# ��������� ��������� ������� ����������
foreach { p } { Pgtcl tls md5 crc32 } {
package require $p
}
# ��������� �������� ��� ���������� � ������ ������
foreach { s } { lib mainthreadtcp protocol protocolt } {
uplevel #0 source $s.tcl
}
}]
# ���������������� � �������� ��������� ������ � �������� �������������� � ��������� (�� �������) ���
proc _Accept {idsocket ipaddr port} {
# ��������� ������� ������ � ��������� ����� ������ ��������������
after idle [list Accept $idsocket $ipaddr $port]
}
# ����������, �������� ����� � ��������� ���
proc Accept { idsocket addr port } {
global Main
# ���������, ���� �� ��������� ����
if { [tsv::get TcpTpool CountJobs] > $Main(TcpPool,maxjobs) } {
# ��������� ����� ���. ��������� �����. ���������� � ��������� ������� �� �������
close $idsocket
return
}
# �������� ����� � �������� �������������� � ������������� ����������� ������
tsv::incr TcpTpool CountJobs
thread::detach $idsocket
tpool::post -detached -nowait $Main(tcptpid) [list Accept:Thread $addr $idsocket]
}
# ��������� �������� ����������� ������ ������ �� ������
proc Accept:Thread { addr idsocket } {
global ProcedureExec
# ��� ��� ������ �������������� ���������� ���, ����������� �� �������, ���������� ����
set handler [clock click -microseconds]
set ProcedureExec($handler) -2
# ���������, ����� �� ������� ����� � ���������� ���, ������ 60 ������ �� ������� �������
after 60000 Timer:CheckConnectedSocket $handler $idsocket $addr
# ������������, ����� ������������ �� �������� ��������������, ����� � ������� ���
thread::attach $idsocket
# ������������� �����
# �����, ��� ���������� ��������� ������ ������ � ������, ����� ������ ���� � ������������� ������
chan configure $idsocket -blocking 0 -buffering line -encoding binary -translation binary
# ������ ���������� ���������� ������ ������ � ������
# ��� ������������� ������ �� ������, ����������� ��������� SocketEventHandler:Thread
chan event $idsocket readable [list SocketEventHandler:Thread $handler $idsocket $addr]
# ��������� ��� ������ �� ������� ��������� ����������
vwait Main($idsocket,IsRun)
}
# ���������, ����� �� ������� ����� � ���������� ���
proc Timer:CheckConnectedSocket { handler idsocket addr } {
global ProcedureExec
if { $ProcedureExec($handler) == -1 } return
if { $ProcedureExec($handler) in "-2 1" } {
# ���������, �� ����������� �� � ������� ������ �������� ������ �� ������� �������
set p [chan pending output $idsocket]
if { $p == 0 } {
# �������� ������ ������� ���������. ����������� ���
Exit:Thread $handler $idsocket
return
}
}
# �������� ������ ������� ������������. ��������� ���������� �������� ����� ���� �������
after 1000 Timer:CheckConnectedSocket $handler $idsocket $addr
}
proc Exit:Thread { handler idsocket } {
global ProcedureExec
set ProcedureExec($handler) -1
# �������������� ���������� ������� �����
tsv::incr TcpTpool CountJobs -1
# ������������� ���������� ���������� ������ ������ � ������
catch { chan event $idsocket readable {} }
# ��������� �����
catch { chan close $idsocket }
# �������� �������� ���������� ��� ��������� ����
set Main($idsocket,IsRun) 0
}
# ������ ������ � ������
proc SocketEventHandler:Thread { handler idsocket addr } {
global ProcedureExec
if { [chan eof $idsocket] || [catch {chan gets $idsocket pkt} err] != 0 } {
Exit:Thread $handler $idsocket
return
} else {
# ����� �������� ��� �� ��������� ����������� ������
# ���������� pkt �������� ���������� ������ �� �������
set ProcedureExec($handler) 1
}
}