Server端-監聽(draft)
設計要點:
1
2
3
4
5
6
| Socket()
Bind()綁定監聽端口
Listen() 設置監聽隊列
Accept() 循環等待客戶端連接
Receive()
Send()
|
1
2
3
4
5
6
7
8
9
10
11
12
13
| //Socket(): 創建一個負責監聽的Socket (流式的tcp)
Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Any; //你ip有變化,它會跟著變
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//Bind()綁定監聽端口: 讓負責監聽的Socket綁定IP位址和Port端口號
socketWatch.Bind(point);
ShowMsg("監聽成功");
//Listen() 設置監聽隊列
socketWatch.Listen(10);//設置監聽隊列
//Accept() 循環等待客戶端連接
Socket socketSend = socketWatch.Accept(); //TODO: thread + while
//Receive()
ShowMsg(socketSend.RemoteEndPoint.ToString()+"連接成功");
|
完整Code(Draft)
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
| private void btnStart_Click(object sender, EventArgs e)
{
//創建一個負責監聽的Socket (流式的tcp)
Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//創建IP地址和Port端口號 對象
IPAddress ip = IPAddress.Any; //你ip有變化,它會跟著變 //IPAddress.Parse(txtIP.Text);//寫死了,不好
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//讓負責監聽的Socket綁定IP位址和Port端口號
socketWatch.Bind(point); //我綁定了point等於綁定了ip,因為point裡有IP:Port
ShowMsg("監聽成功");
//設置監聽隊列
//監聽隊列指的就是,
//在某一個時間點內,能夠連入Server端的最大Clinet端的數量(不是人滿的意思),當到達限量時就只能排隊
//例如廁所裡面,廁所有5間,最大容量5個人,第6個就只能排隊了
//而這邊的監聽隊列就是,當到達這個限定的時候(最大容量),只能排隊了
//如果有人問,像這種情況資料庫怎麼優化呀?
//最簡單的方法就是,花錢多買服務器就解決啦 XDD,但不能這麼說,
//就說"排隊咩",儘量把等待時間減少就可以了
socketWatch.Listen(10);//設置監聽隊列
//Accept()等待客戶的連接
//負責監聽的Socket來接收客戶端的連接
//創建跟客戶端通信的Socket
//為什麼只能連一個,因為Accept它接收完了程式就往下走了
//如果要連很多就要加上while循環,並用線程才不會卡死畫面
Socket socketSend = socketWatch.Accept(); //這行讓視窗卡死了,有人連進來就不卡了,要拿線程去做這件事
ShowMsg(socketSend.RemoteEndPoint.ToString()+"連接成功");
}
void ShowMsg(string str) {
//用Append追加文字。不用text,因為text會覆蓋掉之前的值
txtLog.AppendText(str+"\r\n");
}
|
TODO:需要解決兩件事:
- 只能接受一個用戶端 => while(true)解決
- 尚未有用戶端連進來前,畫面會假死(卡死) => 開一個新的thread
Server端-監聽2
設計要點:
- 使用循環
while(true)等待客戶連接 => 解決只能接受一個用戶端的問題。 - 開一個新的
thread執行緒去執行.Accept()=> 解決尚未有用戶端連進來前,畫面會假死(卡死)的問題。
thread執行緒帶參數的方法,傳入的參數必須是object類型
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
| private void btnStart_Click(object sender, EventArgs e)
{
//創建一個負責監聽的Socket (流式的tcp)
Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//創建IP地址和Port端口號 對象
IPAddress ip = IPAddress.Any; //你ip有變化,它會跟著變 //IPAddress.Parse(txtIP.Text);//寫死了,不好
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//監聽
socketWatch.Bind(point);
ShowMsg("監聽成功");
socketWatch.Listen(10);//設置監聽隊列
Thread th = new Thread(Listen);
th.IsBackground = true;
th.Start(socketWatch);
}
/// <summary>
/// 等待客戶端的連接,並且創建與之通信的Socket
/// </summary>
void Listen(object o) {
Socket socketWatch = o as Socket;
while (true)
{
//等待客戶端的連接,並且創建跟客戶端通信的Socket
Socket socketSend = socketWatch.Accept();
//192.168.11.78 連接成功
ShowMsg(socketSend.RemoteEndPoint.ToString() + "連接成功");
}
}
|
完整Code
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
| private void btnStart_Click(object sender, EventArgs e)
{
//創建一個負責監聽的Socket (流式的tcp)
Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//創建IP地址和Port端口號 對象
IPAddress ip = IPAddress.Any; //你ip有變化,它會跟著變 //IPAddress.Parse(txtIP.Text);//寫死了,不好
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//讓負責監聽的Socket綁定IP位址和Port端口號
socketWatch.Bind(point); //我綁定了point等於綁定了ip,因為point裡有IP:Port
ShowMsg("監聽成功");
//設置監聽隊列
//監聽隊列指的就是,
//在某一個時間點內,能夠連入Server端的最大Clinet端的數量(不是人滿的意思),當到達限量時就只能排隊
//例如廁所裡面,廁所有5間,最大容量5個人,第6個就只能排隊了
//而這邊的監聽隊列就是,當到達這個限定的時候(最大容量),只能排隊了
//如果有人問,像這種情況資料庫怎麼優化呀?
//最簡單的方法就是,花錢多買服務器就解決啦 XDD,但不能這麼說,
//就說"排隊咩",儘量把等待時間減少就可以了
socketWatch.Listen(10);//設置監聽隊列
//負責監聽的Socket來接收客戶端的連接
//等待客戶端的連接,並且創建跟客戶端通信的Socket
//為什麼只能連一個,因為Accept它接收完了程式就往下走了
//如果要連很多就要加上while循環,並用線程才不會卡死畫面
//Socket socketSend = socketWatch.Accept(); //這行讓視窗卡死了,有人連進來就不卡了,要拿線程去做這件事
//192.168.11.78 連接成功
//ShowMsg(socketSend.RemoteEndPoint.ToString()+"連接成功");
Thread th = new Thread(Listen);
th.IsBackground = true;
th.Start(socketWatch); //從這傳入Listen方法要的參數
}
/// <summary>
/// 等待客戶端的連接,並且創建與之通信的Socket
/// </summary>
void Listen(object o) { //必須是object類型
Socket socketWatch = o as Socket //用as強制轉型
while (true)
{
//等待客戶端的連接,並且創建跟客戶端通信的Socket
Socket socketSend = socketWatch.Accept();
//192.168.11.78 連接成功
ShowMsg(socketSend.RemoteEndPoint.ToString() + "連接成功");
}
}
void ShowMsg(string str) {
//用Append追加文字。不用text,因為text會覆蓋掉之前的值
txtLog.AppendText(str+"\r\n");
}
private void frmServer_Load(object sender, EventArgs e)
{
//取消跨線程的檢查
Control.CheckForIllegalCrossThreadCalls = false;
}
|
創建和客戶端通信的Socket(Code)
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
| namespace ServerSocket
{
public partial class frmServer : Form {
public frmServer() {
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
//創建一個負責監聽的Socket (流式的tcp)
Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//創建IP地址和Port端口號 對象
IPAddress ip = IPAddress.Any; //你ip有變化,它會跟著變 //IPAddress.Parse(txtIP.Text);//寫死了,不好
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//讓負責監聽的Socket綁定IP位址和Port端口號
socketWatch.Bind(point); //我綁定了point等於綁定了ip,因為point裡有IP:Port
ShowMsg("監聽成功");
//設置監聽隊列
//監聽隊列指的就是,
//在某一個時間點內,能夠連入Server端的最大Clinet端的數量(不是人滿的意思),當到達限量時就只能排隊
//例如廁所裡面,廁所有5間,最大容量5個人,第6個就只能排隊了
//而這邊的監聽隊列就是,當到達這個限定的時候(最大容量),只能排隊了
//如果有人問,像這種情況資料庫怎麼優化呀?
//最簡單的方法就是,花錢多買服務器就解決啦 XDD,但不能這麼說,
//就說"排隊咩",儘量把等待時間減少就可以了
//監聽
socketWatch.Listen(10);//設置監聽隊列
//負責監聽的Socket來接收客戶端的連接
//等待客戶端的連接,並且創建跟客戶端通信的Socket
//為什麼只能連一個,因為Accept它接收完了程式就往下走了
//如果要連很多就要加上while循環,並用線程才不會卡死畫面
//Socket socketSend = socketWatch.Accept(); //這行讓視窗卡死了因為客戶端不連,我主線程就卡死了,有人連進來就不卡了,要拿線程去做這件事
//192.168.11.78 連接成功
//ShowMsg(socketSend.RemoteEndPoint.ToString()+"連接成功");
//開新線程去執行Listen
Thread th = new Thread(Listen);
th.IsBackground = true;
th.Start(socketWatch); //從這傳入Listen方法要的參數
}
/// <summary>
/// 等待客戶端的連接,並且創建與之通信的Socket
/// </summary>
void Listen(object o) { //必須是object類型
Socket socketWatch = o as Socket; //用as強制轉型
while (true)
{
//等待客戶端的連接,並且創建跟客戶端通信的Socket
Socket socketSend = socketWatch.Accept();
//192.168.11.78 連接成功
ShowMsg(socketSend.RemoteEndPoint.ToString() + "連接成功");
}
}
void ShowMsg(string str) {
//用Append追加文字。不用text,因為text會覆蓋掉之前的值
txtLog.AppendText(str+"\r\n");
}
private void frmServer_Load(object sender, EventArgs e)
{
//取消跨線程的檢查
Control.CheckForIllegalCrossThreadCalls = false;
}
}
}
|
TODO: Receive()、Send()
待續-Socket-服務器接收客戶端發送過來的消息
Thread執行緒帶參數的方法
Thread執行緒執行的方法,如果有參數,那麼這個參數必須是object類型
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
| namespace 多線程執行帶參數的方法 {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//線程執行的方法,如果有參數,那麼這個參數必須是object類型
Thread t = new Thread(Test);
t.IsBackground = true;
t.Start("123"); //在這裡傳參數
}
public void Test(object str) {
string s = (string)str;
MessageBox.Show(s);
}
private void Form1_Load(object sender, EventArgs e)
{
//取消跨線程的檢查
Control.CheckForIllegalCrossThreadCalls = false;
}
}
}
|
Win10啟用Telnet
1
2
| Step1. 控制台 > "開啟或關閉Windows功能"
Step2. 勾選"Telnet用戶端" > 確定
|
1
| telnet 192.168.11.58 50000
|
監聽成功 10.211.55.7:50765 連接成功