一、直接上效果圖

二、Socket握手

三、服務端
Thread threadWatch = null;// 負責監聽客戶端的線程
Socket socketWatch = null;// 負責監聽客戶端的套接字
Socket clientConnection = null;// 負責和客戶端通信的套接字
private void btn_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(ipAddress.Text.ToString()))
{
MessageBox.Show("監聽ip地址不能為空!");
return;
}
if (string.IsNullOrEmpty(port.Text.ToString()))
{
MessageBox.Show("監聽端口不能為空!");
return;
}
// 定義一個套接字用於監聽客戶端發來的消息,包含三個參數(ipv4尋址協議,流式連接,tcp協議)
socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 服務端發送消息需要一個ip地址和端口號
IPAddress ip = IPAddress.Parse(ipAddress.Text.Trim());
// 把ip地址和端口號綁定在網路節點endport上
IPEndPoint endPort = new IPEndPoint(ip, int.Parse(port.Text.Trim()));
// 監聽綁定的網路節點
socketWatch.Bind(endPort);
// 將套接字的監聽隊列長度設置限制為0,0表示無限
socketWatch.Listen(0);
// 創建一個監聽線程
threadWatch = new Thread(WatchConnecting);
threadWatch.IsBackground = true;
threadWatch.Start();
chatContent.AppendText("成功啟動監聽!ip:"+ip+",端口:"+port.Text.Trim()+"\r\n");
}
/// <summary>
/// 監聽客戶端發來的請求
/// </summary>
private void WatchConnecting()
{
//持續不斷監聽客戶端發來的請求
while (true)
{
clientConnection = socketWatch.Accept();
chatContent.AppendText("客戶端連接成功!"+"\r\n");
// 創建一個通信線程
ParameterizedThreadStart pts = new ParameterizedThreadStart(acceptMsg);
Thread thr = new Thread(pts);
thr.IsBackground = true;
thr.Start(clientConnection);
}
}
/// <summary>
/// 接收客戶端發來的消息
/// </summary>
/// <param name="socket">客戶端套接字對象</param>
private void acceptMsg(object socket)
{
Socket socketServer = socket as Socket;
while (true)
{
//創建一個內存緩沖區 其大小為1024*1024字節 即1M
byte[] recMsg = new byte[1024 * 1024];
//將接收到的信息存入到內存緩沖區,並返回其字節數組的長度
int length = socketServer.Receive(recMsg);
//將機器接受到的字節數組轉換為人可以讀懂的字符串
string msg = Encoding.UTF8.GetString(recMsg,0,length);
chatContent.AppendText("客戶端("+GetCurrentTime()+"):"+msg+"\r\n");
}
}
/// <summary>
/// 發送消息到客戶端
/// </summary>
/// <param name="msg"></param>
private void serverSendMsg(string msg)
{
byte[] sendMsg = Encoding.UTF8.GetBytes(msg);
clientConnection.Send(sendMsg);
chatContent.AppendText("服務端("+GetCurrentTime()+"):"+msg+"\r\n");
}
/// <summary>
/// 獲取當前系統時間的方法
/// </summary>
/// <returns>當前時間</returns>
private DateTime GetCurrentTime()
{
DateTime currentTime = new DateTime();
currentTime = DateTime.Now;
return currentTime;
}
四、客戶端
// 創建一個客戶端套接字
Socket clientSocket = null;
// 創建一個監聽服務端的線程
Thread threadServer = null;
private void btn_Click(object sender, EventArgs e)
{
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
if (string.IsNullOrEmpty(ipAddress.Text.ToString()))
{
MessageBox.Show("監聽ip地址不能為空!");
return;
}
if (string.IsNullOrEmpty(port.Text.ToString()))
{
MessageBox.Show("監聽端口不能為空!");
return;
}
IPAddress ip = IPAddress.Parse(ipAddress.Text.Trim());
IPEndPoint endpoint = new IPEndPoint(ip, int.Parse(port.Text.Trim()));
try
{ //這里客戶端套接字連接到網絡節點(服務端)用的方法是Connect 而不是Bind
clientSocket.Connect(endpoint);
}
catch
{
chatContent.AppendText("連接失敗!");
}
// 創建一個線程監聽服務端發來的消息
threadServer = new Thread(recMsg);
threadServer.IsBackground = true;
threadServer.Start();
}
/// <summary>
/// 接收服務端發來的消息
/// </summary>
private void recMsg() {
while (true) //持續監聽服務端發來的消息
{
//定義一個1M的內存緩沖區 用於臨時性存儲接收到的信息
byte[] arrRecMsg = new byte[1024 * 1024];
int length = 0;
try
{
//將客戶端套接字接收到的數據存入內存緩沖區, 並獲取其長度
length = clientSocket.Receive(arrRecMsg);
}
catch
{
return;
}
//將套接字獲取到的字節數組轉換為人可以看懂的字符串
string strRecMsg = Encoding.UTF8.GetString(arrRecMsg, 0, length);
//將發送的信息追加到聊天內容文本框中
chatContent.AppendText("服務端(" + GetCurrentTime() + "):" + strRecMsg + "\r\n");
}
}
/// <summary>
/// 發送消息到服務端
/// </summary>
/// <param name="msg"></param>
private void clientSendMsg(string msg)
{
byte[] sendMsg = Encoding.UTF8.GetBytes(msg);
clientSocket.Send(sendMsg);
chatContent.AppendText("客戶端(" + GetCurrentTime() + "):" + msg + "\r\n");
}
/// <summary>
/// 獲取當前系統時間的方法
/// </summary>
/// <returns>當前時間</returns>
private DateTime GetCurrentTime()
{
DateTime currentTime = new DateTime();
currentTime = DateTime.Now;
return currentTime;
}
GitHub源碼地址:https://github.com/51042309/Socket
