完全是基礎(chǔ),新手可以隨意看看,大??梢躁P(guān)閉瀏覽頁(yè)了,哈哈。TCP/IP協(xié)議TCP/IP是一系列網(wǎng)絡(luò)通信協(xié)議的統(tǒng)稱,其中最核心的兩個(gè)協(xié)議是TCP和IP。TCP稱為傳輸控制協(xié)議,IP稱為互聯(lián)網(wǎng)絡(luò)協(xié)議。 網(wǎng)絡(luò)分層除了OSI模型分層,還有TCP/IP模型分層,將網(wǎng)絡(luò)劃分為四層,應(yīng)用層、傳輸層、網(wǎng)際層、網(wǎng)絡(luò)接口層。TCP/IP模型分層是OSI模型分層的濃縮版 OSI模型和TCP/IP網(wǎng)絡(luò)分層的對(duì)應(yīng)結(jié)構(gòu)及TCP/IP部分協(xié)議族,
TCP三次握手第一次握手:建立連接??蛻舳税l(fā)送連接請(qǐng)求報(bào)文段,將SYN位置為1,Sequence Number為x;然后,客戶端進(jìn)入SYN_SEND狀態(tài),等待服務(wù)器的確認(rèn); 三次握手圖解 在此基礎(chǔ)上,socket連接過(guò)程: 服務(wù)器監(jiān)聽(tīng):服務(wù)器端socket并不定位具體的客戶端socket,而是處于等待監(jiān)聽(tīng)狀態(tài),實(shí)時(shí)監(jiān)控網(wǎng)絡(luò)狀態(tài)。 客戶端請(qǐng)求:客戶端clientSocket發(fā)送連接請(qǐng)求,目標(biāo)是服務(wù)器的serverSocket。為此,clientSocket必須知道serverSocket的地址和端口號(hào),進(jìn)行掃描發(fā)出連接請(qǐng)求。 連接確認(rèn):當(dāng)服務(wù)器socket監(jiān)聽(tīng)到或者是受到客戶端socket的連接請(qǐng)求時(shí),服務(wù)器就響應(yīng)客戶端的請(qǐng)求,建議一個(gè)新的socket,把服務(wù)器socket發(fā)送給客戶端,一旦客戶端確認(rèn)連接,則連接建立。 注:在連接確認(rèn)階段:服務(wù)器socket即使在和一個(gè)客戶端socket建立連接后,還在處于監(jiān)聽(tīng)狀態(tài),仍然可以接收到其他客戶端的連接請(qǐng)求,這也是一對(duì)多產(chǎn)生的原因。 socket連接原理知道了,此處編寫最基本最簡(jiǎn)單的socket通信: 客戶端代碼: /// <summary>
/// 客戶端發(fā)送與服務(wù)端的連接請(qǐng)求,創(chuàng)建與之通信用的Socket
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnLink_Click(object sender, EventArgs e)
{
try
{
//定義一個(gè)用于請(qǐng)求連接服務(wù)器的IP和端口號(hào)
IPEndPoint ip = new IPEndPoint(IPAddress.Parse(txtIp.Text), Convert.ToInt32(txtPort.Text));//txtIP:IP地址;txtPort:端口號(hào)
//定義一個(gè)套接字用于請(qǐng)求連接服務(wù)器,包含三個(gè)參數(shù)(IP4尋址協(xié)議,流式連接,Tcp協(xié)議)
socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//請(qǐng)求連接服務(wù)端
clientSocket.Connect(ip);
//創(chuàng)建一個(gè)通信線程,避免阻塞主線程
Thread th = new Thread(CRecive);
//設(shè)置為后臺(tái)線程,隨著主線程退出而退出
th.IsBackground = true;
//啟動(dòng)線程
th.Start(clientSocket);
//顯示與服務(wù)端連接情況
ShowMsg($"{clientSocket.RemoteEndPoint.ToString()}:已連接");
}
catch (Exception ex)
{
//提示套接字監(jiān)聽(tīng)異常
ShowMsg($"網(wǎng)絡(luò)錯(cuò)誤");
}
}
/// <summary>
/// 客戶端不停的接收服務(wù)端發(fā)送過(guò)來(lái)的消息
/// </summary>
/// <param name="o"></param>
void CRecive(object o)
{
Socket socketSend = o as Socket;
while (true)
{
try
{
//創(chuàng)建一個(gè)內(nèi)存緩沖區(qū),其大小為1024*1024字節(jié) 即1M
byte[] buffer = new byte[1024 * 1024];
//將接收到的信息存入到內(nèi)存緩沖區(qū),并返回其字節(jié)數(shù)組的長(zhǎng)度
int length = socketSend.Receive(buffer);
if (length == 0)
{
ShowMsg($"{socketSend.RemoteEndPoint.ToString()}:已斷開(kāi)連接");
break;
}
//將機(jī)器接受到的字節(jié)數(shù)組轉(zhuǎn)換為人可以讀懂的字符串
string str = Encoding.UTF8.GetString(buffer, 0, length);
//將發(fā)送的字符串信息附加到ShowMsg上
ShowMsg($"Ta({socketSend.RemoteEndPoint.ToString()}):{str}");
}
catch (Exception ex)
{ }
}
}
客戶端向服務(wù)端發(fā)送數(shù)據(jù): clientSocket.Send(Encoding.UTF8.GetBytes($"{txtWrite.Text}"));
服務(wù)端代碼: /// <summary>
/// 開(kāi)啟監(jiān)聽(tīng),等待客戶端連接
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnMonitor_Click(object sender, EventArgs e)
{
try
{
//定義一個(gè)套接字用于監(jiān)聽(tīng)客戶端發(fā)來(lái)的消息,包含三個(gè)參數(shù)(IP4尋址協(xié)議,流式連接,Tcp協(xié)議)
socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//服務(wù)端發(fā)送信息需要一個(gè)IP地址和端口號(hào)
IPAddress ip = IPAddress.Parse(txtIp.Text);//IPAddress.Any;
//將IP地址和端口號(hào)綁定到網(wǎng)絡(luò)節(jié)點(diǎn)point上
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//監(jiān)聽(tīng)綁定的網(wǎng)絡(luò)節(jié)點(diǎn)
socketWatch.Bind(point);
ShowMsg("開(kāi)始監(jiān)聽(tīng)。。。");
//將套接字的監(jiān)聽(tīng)隊(duì)列長(zhǎng)度限制為10
socketWatch.Listen(10);
//負(fù)責(zé)監(jiān)聽(tīng)客戶端的線程:創(chuàng)建一個(gè)監(jiān)聽(tīng)線程
Thread th = new Thread(SListen);
//將窗體線程設(shè)置為與后臺(tái)同步,隨著主線程結(jié)束而結(jié)束
th.IsBackground = true;
//啟動(dòng)線程
th.Start(socketWatch);
}
catch (Exception ex)
{ }
}
/// <summary>
/// 等待客戶端的連接 并且創(chuàng)建與之通信用的Socket
/// </summary>
/// <param name="o"></param>
void SListen(object o)
{
Socket socketWatch = o as Socket;
while (true)
{
try
{
//等待客戶端的連接,并且創(chuàng)建與之通信用的Socket
Socket serverSocket = socketWatch.Accept();
//獲取客戶端網(wǎng)絡(luò)結(jié)點(diǎn)號(hào)
string socketIP = serverSocket.RemoteEndPoint.ToString();
ShowMsg($"{socketIP}:已連接");
//創(chuàng)建一個(gè)通信線程,避免阻塞主線程
Thread th = new Thread(SRecive);
th.IsBackground = true;
th.Start(serverSocket);
}
catch
{ }
}
}
/// <summary>
/// 服務(wù)端不停的接收客戶端發(fā)送過(guò)來(lái)的消息
/// </summary>
/// <param name="o"></param>
void SRecive(object o)
{
Socket socketSend = o as Socket;
while (true)
{
//將接收到的信息存入到內(nèi)存緩沖區(qū),并返回其字節(jié)數(shù)組的長(zhǎng)度
try
{
//創(chuàng)建一個(gè)內(nèi)存緩沖區(qū),其大小為1024*1024字節(jié) 即1M
byte[] buffer = new byte[1024 * 1024];
//接收客戶端發(fā)送過(guò)來(lái)的消息
int length = socketSend.Receive(buffer);
if (length == 0)
{
ShowMsg($"{socketSend.RemoteEndPoint.ToString()}:已斷開(kāi)連接");
break;
}
//將機(jī)器接受到的字節(jié)數(shù)組轉(zhuǎn)換為人可以讀懂的字符串
string str = Encoding.UTF8.GetString(buffer, 0, length);
//將發(fā)送的字符串信息附加到ShowMsg上
ShowMsg($"Ta({socketSend.RemoteEndPoint.ToString()}):{str}");
}
catch (Exception ex) { }
}
}
服務(wù)端向已連接的客戶端發(fā)送數(shù)據(jù): serverSocket.Send(Encoding.UTF8.GetBytes($"{txtWrite.Text}")); |
|
|