要求:
1.可以完成一對一的通信;
2.實作服務端對用戶端一對多的選擇發送;
3.可以實作服務端的群發功能;
4.可以實作用戶端檔案的發送;
要點:
伺服器端:
第一步:用指定的端口号和伺服器的ip建立一個EndPoint對像;
第二步:建立一個Socket對像;
第三步:用socket對像的Bind()方法綁定EndPoint;
第四步:用socket對像的Listen()方法開始監聽;
第五步:接受到用戶端的連接配接,用socket對像的Accept()方法建立新的socket對像用于和請求的用戶端進行通信;
第六步:通信結束後一定記得關閉socket;
用戶端:
第一步:用指定的端口号和伺服器的ip建立一個EndPoint對像;
第二步:建立一個Socket對像;
第三步:用socket對像的Connect()方法以上面建立的EndPoint對像做為參數,向伺服器發出連接配接請求;
第四步:如果連接配接成功,就用socket對像的Send()方法向伺服器發送資訊;
第五步:用socket對像的Receive()方法接受伺服器發來的資訊 ;
第六步:通信結束後一定記得關閉socket;
服務端代碼如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
namespace Socket_ServerAndClient
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
TextBox.CheckForIllegalCrossThreadCalls = false;
}
Thread threadWatch = null;
Socket socketWatch = null;
/// <summary>
/// 建立服務
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
socketWatch = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
IPAddress address = IPAddress.Parse(txtIP.Text.Trim());
IPEndPoint endpoint = new IPEndPoint(address,int.Parse(txtPort.Text.Trim()));
socketWatch.Bind(endpoint);
socketWatch.Listen(10);
threadWatch = new Thread(WatchConnection);
threadWatch.IsBackground = true;
threadWatch.Start();
ShowMsg("伺服器監聽成功......");
}
//Socket sokConnection = null;
Dictionary<string, Socket> dict = new Dictionary<string, Socket>();
Dictionary<string, Thread> dictThread = new Dictionary<string, Thread>();
/// <summary>
/// 監聽用戶端的請求方法
/// </summary>
/// <param name="obj"></param>
private void WatchConnection(object obj)
{
while (true)
{
// 負責通信的套接字
Socket sokConnection = socketWatch.Accept();
lb_Online.Items.Add(sokConnection.RemoteEndPoint.ToString());
dict.Add(sokConnection.RemoteEndPoint.ToString(),sokConnection);
//建立通信線程
ParameterizedThreadStart pts = new ParameterizedThreadStart(RecMsg);// 委托
Thread thr = new Thread(pts);
thr.IsBackground = true;
thr.Start(sokConnection);
dictThread.Add(sokConnection.RemoteEndPoint.ToString(),thr);
ShowMsg("用戶端連接配接成功......"+sokConnection.RemoteEndPoint.ToString());
}
}
/// <summary>
/// 服務端負責監聽用戶端發送消息的方法
/// </summary>
void RecMsg(object socketClient)
{
Socket socketClients = socketClient as Socket;
while (true)
{
byte[] arrMsgRec = new byte[1024 * 1024 * 2];
int length = -1;
try
{
length = socketClients.Receive(arrMsgRec);
}
catch (SocketException ex)
{
ShowMsg("異常:" + ex.Message);
// 從 通信套接字 集合中删除被中斷連接配接的套接字對象
dict.Remove(socketClients.RemoteEndPoint.ToString());
// 從 通信線程 集合中删除被中斷連接配接的套接字對象
dictThread.Remove(socketClients.RemoteEndPoint.ToString());
// 從 清單 中移除 IP&Port
lb_Online.Items.Remove(socketClients.RemoteEndPoint.ToString());
break;
}
catch (Exception ex)
{
ShowMsg("異常:" + ex.Message);
break;
}
// 判斷第一個發送過來的資料如果是1,則代表發送過來的是文本資料
if (arrMsgRec[0] == 0)
{
string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec, 1, length-1);
ShowMsg(strMsgRec);
}
// 若是1則發送過來的是檔案資料(文檔,圖檔,視訊等。。。)
else if(arrMsgRec[0] == 1)
{
// 儲存檔案選擇框對象
SaveFileDialog sfd = new SaveFileDialog();
// 選擇檔案路徑
if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
// 獲得儲存檔案的路徑
string fileSavePath = sfd.FileName;
// 建立檔案流,然後讓檔案流根據路徑建立一個檔案
using (FileStream fs = new FileStream(fileSavePath, FileMode.Create))
{
fs.Write(arrMsgRec, 1, length - 1);
ShowMsg("檔案儲存成功:"+fileSavePath);
}
}
}
}
}
private void ShowMsg(string p)
{
txtMsg.AppendText(p+"\r\n");
}
/// <summary>
/// 發送消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Send_Click_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(lb_Online.Text))
{
MessageBox.Show("請選擇發送的好友!!!");
}
else
{
string strMsg = tb_Msg_Send.Text.Trim();
byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
string strClientKey = lb_Online.Text;
try
{
dict[strClientKey].Send(arrMsg);
ShowMsg("發送了資料出去:"+strMsg);
}
catch (SocketException ex)
{
ShowMsg("發送時異常:" + ex.Message);
}
catch(Exception ex)
{
ShowMsg("發送時異常:" + ex.Message);
}
// sokConnection.Send(arrMsg);
ShowMsg("發送了資料出去:"+strMsg);
}
}
/// <summary>
/// 群發消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SendToAll_Click(object sender, EventArgs e)
{
string strMsg = txtMsg.Text.Trim();
byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
foreach (Socket item in dict.Values)
{
item.Send(arrMsg);
}
ShowMsg("群發完畢!!!:)");
}
}
}
用戶端代碼如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
namespace Socket_Client
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
TextBox.CheckForIllegalCrossThreadCalls = false;
}
Thread threadRec = null;
Socket socketClient = null;
private void btn_Connect_Click(object sender, EventArgs e)
{
IPAddress address = IPAddress.Parse(tb_IP.Text.Trim());
IPEndPoint endport = new IPEndPoint(address,int.Parse(tb_Port.Text.Trim()));
socketClient = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
socketClient.Connect(endport);
threadRec = new Thread(RecMsg);
threadRec.IsBackground = true;
threadRec.Start();
}
void RecMsg()
{
while (true)
{
byte[] arrMsgRec = new byte[1024*1024*2];
int length = socketClient.Receive(arrMsgRec);
string strMsgRec = System.Text.Encoding.UTF8.GetString(arrMsgRec,0,length);
ShowMsg(strMsgRec);
}
}
private void ShowMsg(string msg)
{
tb_Msg.AppendText(msg+"\r\n");
}
private void btnSendMsg_Click(object sender, EventArgs e)
{
string strMsg = txtMsgSend.Text.Trim();
byte[] arrMsg = System.Text.Encoding.UTF8.GetBytes(strMsg);
byte[] arrMsgSend = new byte[arrMsg.Length];
// 添加辨別位,0代表發送的是文字
arrMsgSend[0] = 0;
Buffer.BlockCopy(arrMsg, 0, arrMsgSend, 1, arrMsg.Length);
socketClient.Send(arrMsg);
ShowMsg("I say:"+strMsg);
}
/// <summary>
/// 選擇檔案
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btChoseFile_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
txtFilePath.Text = ofd.FileName;
}
}
/// <summary>
/// 發送檔案
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btSendFile_Click(object sender, EventArgs e)
{
using (FileStream fs = new FileStream())
{
byte[] arrFile = new byte[1024*1024*2];
int length = fs.Read(arrFile, 0, arrFile.Length);
byte[] arrFileSend = new byte[length+1];
arrFileSend[0] = 1;// 代表檔案資料
// 将數組 arrFile 裡的資料從第零個資料拷貝到 數組 arrFileSend 裡面,從第1個開始,拷貝length個資料
Buffer.BlockCopy(arrFile, 0, arrFileSend, 1, length);
socketClient.Send(arrFileSend);
}
}
}
}
程式運作截圖:

轉載于:https://www.cnblogs.com/IamJiangXiaoKun/p/4952389.html