1.什么是Socket
Sockets 是一種進程通信機制,是一個通信鏈的句柄(其實就是兩個程序通信用的)
2.分類
- 流式套接字(SOCK_STREAM):提供了一種可靠的、面向連接的雙向數據傳輸服務。實現了數據無差錯,無重復的發送,內設流量控制,被傳輸的數據被看做無記錄邊界的字節流。在TCP/IP協議簇中,使用TCP實現字節流的傳輸,當用戶要發送大批量數據,或對數據傳輸的可靠性有較高要求時使用流式套接字。
- 數據報套接字(SOCK_DGRAM):提供了一種無連接、不可靠的雙向數據傳輸服務。數據以獨立的包形式被發送,並且保留了記錄邊界,不提供可靠性保證。數據在傳輸過程中可能會丟失或重復,並且不能保證在接收端數據按發送順序接收。在TCP/IP協議簇中,使用UDP實現數據報套接字。
- 原始套接字(SOCK_RAW):該套接字允許對較低層協議(如IP或ICMP)進行直接訪問。一般用於對TCP/IP核心協議的網絡編程。
3.相關概念
端口:在Internet上有很多這樣的主機,這些主機一般運行了多個服務軟件,同時提供幾種服務。每種服務都打開一個Socket,並綁定到一個端口上,不同的端口對應於不同的服務(應用程序),因此,在網絡協議中使用端口號識別主機上不同的進程。
例如:http使用80端口,FTP使用21端口。
協議:
TCP是一種面向連接的、可靠的,基於字節流的傳輸層通信協議。為兩台主機提供高可靠性的數據通信服務。它可以將源主機的數據無差錯地傳輸到目標主機。當有數據要發送時,對應用進程送來的數據進行分片,以適合於在網絡層中傳輸;當接收到網絡層傳來的分組時,它要對收到的分組進行確認,還要對丟失的分組設置超時重發等。為此TCP需要增加額外的許多開銷,以便在數據傳輸過程中進行一些必要的控制,確保數據的可靠傳輸。因此,TCP傳輸的效率比較低。
UDP是一種簡單的、面向數據報的無連接的協議,提供的是不一定可靠的傳輸服務。所謂“無連接”是指在正式通信前不必與對方先建立連接,不管對方狀態如何都直接發送過去。這與發手機短信非常相似,只要知道對方的手機號就可以了,不要考慮對方手機處於什么狀態。UDP雖然不能保證數據傳輸的可靠性,但數據傳輸的效率較高。
4.控制台簡單例子
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
/// <summary>
/// 服務器端
/// </summary>
namespace SocketServer
{
class Program
{
private static byte[] result = new byte[50];
private static int myProt = 8885;//端口
static Socket serverSocket;
static void Main(string[] args)
{
IPAddress ip = IPAddress.Parse("127.0.0.1");//IP地址
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.Bind(new IPEndPoint(ip, myProt));//綁定IP地址端口
serverSocket.Listen(10);//設定最多10個排隊連接請求
Console.WriteLine("啟動監聽{0}成功",serverSocket.LocalEndPoint.ToString());
//通過Clientsoket發送數據
Thread myThread = new Thread(ListenClientConnect);
myThread.Start();
Console.ReadLine();
}
/// <summary>
/// 監聽客戶端連接
/// </summary>
private static void ListenClientConnect()
{
while (true)
{
Socket clientSocket = serverSocket.Accept();
clientSocket.Send(Encoding.ASCII.GetBytes("Server Say Hello"));
Thread receiveThread = new Thread(ReceiveMessage);
receiveThread.Start(clientSocket);
}
}
/// <summary>
/// 接收消息
/// </summary>
/// <param name="clientSocket"></param>
private static void ReceiveMessage(object clientSocket)
{
Socket myClientSocket = (Socket)clientSocket;
while (true)
{
try
{
int receiveNumber = myClientSocket.Receive(result);
if (receiveNumber == 0)
{
break;
}
Console.WriteLine("接受客戶端{0}的消息{1}", myClientSocket.RemoteEndPoint.ToString(), Encoding.ASCII.GetString(result));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}
myClientSocket.Shutdown(SocketShutdown.Both);
myClientSocket.Close();
}
}
}
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
/// <summary>
/// 客戶端
/// </summary>
namespace SocketClient
{
class Program
{
private static byte[] result = new byte[1024];
static void Main(string[] args)
{
IPAddress ip = IPAddress.Parse("127.0.0.1");
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
clientSocket.Connect(new IPEndPoint(ip, 8885)); //配置服務器IP與端口
Console.WriteLine("連接服務器成功");
}
catch
{
Console.WriteLine("連接服務器失敗,請按任意鍵退出!");
Console.Read();
return;
}
//通過clientSocket接收數據
int receiveLength = clientSocket.Receive(result);
Console.WriteLine("接收服務器消息:{0}", Encoding.ASCII.GetString(result, 0, receiveLength));
try
{
string sendMessage = "client send Message Hello @ " + DateTime.Now;
clientSocket.Send(Encoding.ASCII.GetBytes(sendMessage));
Console.WriteLine("向服務器發送消息:{0}",sendMessage);
}
finally
{
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
}
Console.WriteLine("發送完畢,按回車鍵退出");
Console.ReadLine();
}
}
}
運行之后的效果是: