C#網絡編程


Socket編程

Socket中文譯名為套接字,所謂的套接字其實是網絡傳輸中端點的抽象表示。
那么,端點又是什么呢?它其實就是網絡傳輸中傳輸的起點或者終點,只是這個起點或者終點比較特殊,它是由兩部分組成:ip地址和端口號,用(Ip地址:端口號)的形式表示。套接字是TCP/IP的網絡通信的基本操作單元。
那么,什么又是TCP/IP網絡通信呢?這是一個很寬泛的概念,說的直白點,我們現在所用的互聯網就是基於這種架構研發的,它是互聯網的基礎通信架構。涉及的概念也特別多。比如說IP,TCP/UDP協議,ICMP,以及我們更加熟悉的http、ftp,但是在C#網絡編程當中,我們最常用的也就是TCP/UDP的概念,了解一下這兩個概念,以及相關的編程方法,就可以應對很對網絡編程了。

TCP協議

參考這個博文
tcp協議詳解

利用Socket編程,我們可以搭建建議的客戶端與服務器端,相關步驟和代碼如下所示:
Socket編程-Tcp服務器端:

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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace Socket_Tcp
{
class Program
{
static void Main(string[] args)
{
//服務器端
//1.創建socket
Socket tcpServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

//綁定ip地址和端口號(每個軟件都會有一個端口號)
IPAddress ipAddress = new IPAddress(new byte[] {192,168,101,8 }); //IP地址可以用ipconfig查看一下
EndPoint endPoint = new IPEndPoint(ipAddress,2333); //IPEndPoint對端口號和ip地址進行了封裝,2333是隨便寫的一個端口號
tcpServer.Bind(endPoint);

//開始監聽
tcpServer.Listen(150); //最多允許150的客戶端進行連接

//clientSocket為返回的客戶端消息
Socket clientSocket = tcpServer.Accept();//暫停當前線程,直到有一個客戶端連接之后,再執行該行以下的代碼
string message = "我往客戶端發消息";
var bypeMessage = Encoding.UTF8.GetBytes(message); //將Message轉換為byte類型
clientSocket.Send(bypeMessage);

//接收客戶端返回的消息
byte[] backDate = new byte[1024];//用來接收服務器返回的消息
int length = clientSocket.Receive(backDate);
string backMessage = Encoding.UTF8.GetString(backDate, 0, length);
Console.WriteLine(backMessage);
Console.ReadKey();
}
}
}

socket編程-Tcp客戶端

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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace Socket_Tcp_Client
{
class Program
{
static void Main(string[] args)
{
//客戶端
//創建Socket
Socket tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

//發起建立連接的請求
IPAddress ipAddress = IPAddress.Parse("192.168.101.8");
EndPoint endPoint = new IPEndPoint(ipAddress, 2333);
tcpClient.Connect(endPoint); // 客戶端不需要監聽,但是要和服務器連接,且Ip地址和端口號要和服務器保持一致
byte[] date = new byte[1024];
int length = tcpClient.Receive(date); // 用date存儲接收過來的數據,長度是length

string message = Encoding.UTF8.GetString(date, 0, length);//將接收的date轉換為string類型
Console.WriteLine(message);

//向服務器返回消息
string backMessage = Console.ReadLine();//返回的消息由用戶輸入
tcpClient.Send(Encoding.UTF8.GetBytes(backMessage));//向服務器發送消息

Console.ReadKey();
}
}
}

UDP協議

參考這個博文
UDP協議學習

這個博文當中已經說明了這么幾種情況:
1.首先,UDP是無連接協議,所以對比一下TCP協議的編程方式,我們不難發現,UDP當中少了建立連接這個過程。
2.UDP協議是一種數據報協議,所以不同於TCP協議采用的Stream方式,而是采用Dgram的方式,這個在Socket編程當中也有所體現。

UDP服務器端

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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace udp_server
{
class Program
{
private static Socket udpServer;
static void Main(string[] args)
{
//創建Socket
udpServer = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);

//綁定ip和端口號
udpServer.Bind(new IPEndPoint(IPAddress.Parse("192.168.101.8"),2333));

//接收數據
new Thread(ReceiveMessage) { IsBackground = true }.Start();//設置成后台線程,因為程序運行結束,也就不需要這個線程了。


udpServer.Close();
Console.ReadKey();
}

private static void ReceiveMessage()
{
while (true)
{
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
byte[] data = new byte[1024];
int length = udpServer.ReceiveFrom(data, ref remoteEndPoint);

string message = Encoding.UTF8.GetString(data, 0, length);

Console.WriteLine("從ip: " + (remoteEndPoint as IPEndPoint).Address.ToString()
+ (remoteEndPoint as IPEndPoint).Port + "收到了數據: " + message);
}
}
}
}

UDP客戶端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22大專欄  C#網絡編程pan>
23
24
25
26
27
28
29
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace udp_socket_Client
{
class Program
{
static void Main(string[] args)
{
Socket udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram
, ProtocolType.Udp);
//發送數據
while (true)
{
EndPoint serverPoint = new IPEndPoint(IPAddress.Parse("192.168.101.8"), 2333));
string message = Console.ReadLine();
byte[] data = Encoding.UTF8.GetBytes(message);
udpClient.SendTo(data, serverPoint);
}

Console.ReadKey();
}
}
}

監聽器

TCP和UDP編程除了可以使用Socket以外,還可以使用TcpListener和UdpClient,具體編碼和步驟如下所示。

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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace Tcplistener_Server
{
class Program
{
static void Main(string[] args)
{
//1.對socket進行封裝,tcpListener內本身包含套接字
TcpListener listener = new TcpListener(IPAddress.Parse("192.168.101.8"),2223);

//2.進行監聽
listener.Start();

//3.等待用戶連接
TcpClient client = listener.AcceptTcpClient();

//4.獲得客戶端發送過來的數據
NetworkStream stream = client.GetStream();

//5.讀取數據
byte[] data = new byte[1024];
while (true)
{
int length = stream.Read(data, 0, 1024);
string message = Encoding.UTF8.GetString(data, 0, length);
Console.WriteLine("Receive Message: " + message);
}
stream.Close();
client.Close();
listener.Stop();
}
}
}

客戶端

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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace Tcplistener_Cllient
{
class Program
{
static void Main(string[] args)
{
//1.創建TCP對象的時候,就會與服務器建立聯系
TcpClient client = new TcpClient("192.168.101.8", 2223);

//2.通過網絡流獲取數據信息
NetworkStream stream = client.GetStream();

while (true)
{
//手動輸入需要發送的信息
string message = Console.ReadLine();
byte[] data = Encoding.UTF8.GetBytes(message);

//將信息寫入網絡流
stream.Write(data, 0, data.Length);
}

//關閉流
stream.Close();
client.Close();
Console.ReadKey();
}
}
}

UdpClient

消息接收方

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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace _UdpListener
{
class Program
{
static void Main(string[] args)
{
UdpClient udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse("192.168.101.8"),2223));

//接收數據
IPEndPoint point = new IPEndPoint(IPAddress.Any, 0);
byte[] data = udpClient.Receive(ref point);//通過point確定數據來自哪個ip和端口號,並返回接收的數據
string message = Encoding.UTF8.GetString(data);
Console.WriteLine("收到數據: " + message);
udpClient.Close();
Console.ReadKey();
}
}
}

消息發送方

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace _udpListenerClient
{
class Program
{
static void Main(string[] args)
{
UdpClient client = new UdpClient();
string message = Console.ReadLine();
byte[] data = Encoding.UTF8.GetBytes(message);

client.Send(data, data.Length, new IPEndPoint(IPAddress.Parse("192.169.101.8"), 2333));
client.Close();
Console.ReadKey();
}
}
}

TCP和UDP的區別

在看過TCP和UDP的相關資料,以及編寫相關代碼之后,我們不難總結出這兩個協議的這幾個不同之處:

連接方式

TCP需要客戶端與服務器之間的連接操作,連接的時候需要“三次握手”,斷開連接則需要“四次揮手”,而UDP協議則沒有這個過程。

復雜程度

TCP協議相對復雜,這當中包含了容錯機制,以及擁堵的處理等,正式因為如此,TCP的可靠性較高。而UDP則要簡單許多,相對的,UDP的可靠性也比較低下。

傳輸模式

TCP的傳輸,使用的是流模式(Stream),而UDP則采用的是數據報。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM