C#網編Winform(三)
C#網編Winform(三)
一、TCP/IP層次模型
應用層(Application):應用層是個很廣泛的概念,有一些基本相同的系統級TCP/IP應用以及應用協議,也有許多的企業應用和互聯網應用。http協議在應用層運行。
傳輸層(Tanspot):傳輸層包括UDP和TCP,UDP幾乎不對報文進行檢查,而TCP提供傳輸保證。
網絡層(Netwok):網絡層協議由一系列協議組成,包括ICMP、IGMP、RIP、OSPF、IP(v4,v6)等。
鏈路層(Link):又稱為物理數據網絡接口層,負責報文傳輸。
二、端口
- 端口號範圍:0-65535,總共能表示65536個數
按端口號可分為3大類
(1)公認端口(WellKnownPorts):從0到1023,它們緊密綁定(binding)於一些服務。通常這些端口的通訊明確表明了某種服務的協議。例如:80端口實際上總是HTTP通訊。
(2)註冊端口(RegisteredPorts):從1024到49151。它們松散地綁定於一些服務。也就是說有許多服務綁定於這些端口,這些端口同樣用於許多其它目的。例如:許多系統處理動態端口從1024左右開始。
(3)動態和/或私有端口(Dynamicand/orPrivatePorts):從49152到65535。理論上,不應為服務分配這些端口。實際上,機器通常從1024起分配動態端口。
- 通過IP地址確定了網絡中的一臺電腦後,該電腦上可能提供很多提供服務的應用,每一個應用都對應一個端口。
1、Internet上主機一般運行了多個服務軟件 ,同時提供幾種服務,每種服務都打開一個Socket,並綁定到一個端口上,不同的端口對應於不同的服務(應用程序)
例如:http 使用80端口, ftp使用21端口 smtp使用25端口
三、Socket一般應用模式(服務器端和客戶端)
服務器端的Socket(至少需要兩個)
一個負責接收客戶端連接請求(但不負責與客戶端通信)
另一個當成功接收到客戶端的連接便在服務器端產生一個對應的復雜通信的Socket負責和客戶端通信通訊過程服務器端:
01,申請一個socket
02,綁定到一個IP地址和一個端口上
03,開啟偵聽,等待接收連接
04、服務器端接收到連接請求後,產生一個新的socket(端口大於1024)與客戶端建立連接並進行通信,原監聽socket繼續監聽。負責通信的Socket不能無限創建,創建的數量和操作系統有關。客戶端的Socket
必須指定要連接的服務器地址和端口
通過創建一個Socket對象來初始化一個到服務器端的TCP連接通訊過程客戶端:
01,申請一個socket
02,連接服務器(指明IP地址和端口號)
四.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,要連接的遠程主機必須正在監聽指定端口,也就是說你無法隨意連接遠程主機。
五.Socket常用類與API
- 相關類:
IPAddress:包含了一個IP地址
IPEndPoint:包含了一對IP地址和端口號
- 方法:
Socket():創建一個Socket
Bind():綁定一個本地的IP和端口號(IPEndPoint)
Listen():讓Socket偵聽傳入的連接吃那個病,並指定偵聽隊列容量
Connect():初始化與另一個Socket的連接
Accept():接收連接並返回一個新的Socket
Send():輸出數據到Socket
Receive():從Socket中讀取數據
Close():關閉Socket,銷毀連接
六.Winform舉例
// 服務器
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 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<string,Socket> dic=new Dictionary<string, Socket>();
// 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);
break;
}
}
}
//接收消息
void ReceiveMsg(object o)
{
Socket client = o as Socket;
while (true)
{
//接收客戶端發送過來的數據
try
{
//定義byte數組存放從客戶端接收過來的數據
byte[] buffer = new byte[1024 * 1024];
//將接收過來的數據放到buffer中,並返回實際接受數據的長度
int n = client.Receive(buffer);
//將字節轉換成字符串
string words = Encoding.UTF8.GetString(buffer, 0, n);
ShowMsg(client.RemoteEndPoint.ToString() + ":" + words);
}
catch (Exception ex)
{
ShowMsg(ex.Message);
break;
}
}
}
void ShowMsg(string msg)
{
txtLog.AppendText(msg+"\r\n");
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
//主窗體關閉時關閉子線程
}
//給客戶端發送消息
private void btnSend_Click(object sender, EventArgs e)
{
try
{
ShowMsg(txtMsg.Text);
string ip = cboIpPort.Text;
byte[] buffer = Encoding.UTF8.GetBytes(txtMsg.Text);
dic[ip].Send(buffer);
// client.Send(buffer);
}
catch (Exception ex)
{
ShowMsg(ex.Message);
}
}
//客戶端
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private void btnConnection_Click(object sender, EventArgs e)
{
//連接到的目標IP
IPAddress ip = IPAddress.Parse(txtIP.Text);
//IPAddress ip = IPAddress.Any;
//連接到目標IP的哪個應用(端口號!)
IPEndPoint point=new IPEndPoint(ip,int.Parse(txtPort.Text));
try
{
//連接到服務器
client.Connect(point);
ShowMsg("連接成功");
ShowMsg("服務器" + client.RemoteEndPoint.ToString());
ShowMsg("客戶端:" + client.LocalEndPoint.ToString());
//連接成功後,就可以接收服務器發送的信息了
Thread th=new Thread(ReceiveMsg);
th.IsBackground = true;
th.Start();
}
catch (Exception ex)
{
ShowMsg(ex.Message);
}
}
//接收服務器的消息
void ReceiveMsg()
{
while (true)
{
try
{
byte[] buffer = new byte[1024 * 1024];
int n = client.Receive(buffer);
string s = Encoding.UTF8.GetString(buffer, 0, n);
ShowMsg(client.RemoteEndPoint.ToString() + ":" + s);
}
catch (Exception ex)
{
ShowMsg(ex.Message);
break;
}
}
}
void ShowMsg(string msg)
{
txtInfo.AppendText(msg+"\r\n");
}
private void btnSend_Click(object sender, EventArgs e)
{
//客戶端給服務器發消息
if (client!=null)
{
try
{
ShowMsg(txtMsg.Text);
byte[] buffer = Encoding.UTF8.GetBytes(txtMsg.Text);
client.Send(buffer);
}
catch (Exception ex)
{
ShowMsg(ex.Message);
}
}
}
private void ClientForm_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;
}
C#網編Winform(三)