winform制作一個簡單的聊天小程序(剛剛學習到),分享給大家


首先這是服務器端的頁面

#region 監聽ip地址設置(服務器訪問客戶端ip地址設置,獲取客戶端ip地址個端口號)
private void btnStart_Click(object sender, EventArgs e)
{
if (txtIp.Text.Equals("")||txtPort.Text.Equals(""))//判斷是否輸入了ip地址和端口號
{
MessageBox.Show("請輸入ip地址和端口號", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
try
{
//當點擊開始監聽的時候 在服務器端創建一個負責監聽IP地址和端口號的Socket
//addressFamily: Socket:使用的尋址方案,socketType:Socket 的類型,protocolType:Socket 使用的協議。
Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Any;
//創建服務器端網絡端點對象
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//偵聽Soket與本地終結點綁定
socketWatch.Bind(point);
//設置為監聽狀態
socketWatch.Listen(10);
ShowMsg("監聽成功");
//新建線程等待連接,創建通信Socket
Thread th = new Thread(Listen);
th.IsBackground = true;//設置為后台線程
th.Start(socketWatch);
}
catch { }
}

}
Socket socketSend;
Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();

private void Listen(object o)
{
Socket socketWatch = o as Socket;
//循環目的在於使得多個客戶端可以連接服務器
while (true)
{
try
{
//等待客戶端連接,由偵聽的Socket創建一個負責與客戶端通信的Socket
socketSend = socketWatch.Accept();
//將遠程連接的客戶端的IP地址和Socket存入集合中
dicSocket.Add(socketSend.RemoteEndPoint.ToString(), socketSend);
//將遠程連接的客戶端的IP地址和端口號存入下拉框中
cboUsers.Items.Add(socketSend.RemoteEndPoint.ToString());
ShowMsg(socketSend.RemoteEndPoint.ToString() + ";" + "連接成功");//獲取遠程的客戶端ip和端口
//創建新線程不停的接受客戶端發過來的消息
Thread th = new Thread(Receive);
th.IsBackground = true;
th.Start(socketSend);

}
catch{ }
}
}

/// <summary>
/// 服務器端不停地接受客戶端發來的消息
/// </summary>
/// <param name="o"></param>
private void Receive(object o)
{
Socket socketSend = o as Socket;
while (true)
{
try
{
//客戶端連接成功后接受客戶端發來的消息
byte[] buf = new byte[1024 * 1024 * 2];
int r = socketSend.Receive(buf);//實時接收的字節數
//如果客戶端關閉發送有效字節數為0
if (r==0)
{
break;
}
ShowMsg(socketSend.RemoteEndPoint.ToString() + ";" + Encoding.UTF8.GetString(buf, 0, r));
}
catch{ }
}
}

private void ShowMsg(string str)
{
txtLog.AppendText(str + "\r\n");
}
#endregion

#region 服務器向客戶端發送文本信息
private void btnSendMessage_Click(object sender, EventArgs e)
{
if (cboUsers.Text.Equals(""))//判斷是否選擇了客戶端ip地址
{
MessageBox.Show("請選擇客戶端ip地址", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
if (txtMessage.Text.Equals(""))//判斷是否輸入了要發送的消息
{
MessageBox.Show("請輸入要發送的信息", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
string str = txtMessage.Text.Trim();
byte[] buf = Encoding.UTF8.GetBytes(str);
List<byte> byteList = new List<byte>();
//根據自定義的協議,發送的字節數組的第一位為0是表示發送的是文本
byteList.Add(0);
byteList.AddRange(buf);
//泛型集合轉換為新的數組
byte[] newBuffer = byteList.ToArray();
//獲取用戶在下拉框里面的ip地址
try
{
string ip = cboUsers.SelectedItem.ToString();
dicSocket[ip].Send(newBuffer);
}
catch { }
txtMessage.Text = null;
}
}


}
#endregion

#region 服務器向客戶端發送文件
/// <summary>
/// 選擇文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnChoose_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Title = "請選擇您要發送的文件";
ofd.InitialDirectory = @"C:\Users\Public\Pictures\Sample Pictures";
ofd.Filter = "所有文件|*.*";
ofd.ShowDialog();
//把文件路徑顯示在路徑文本框
txtFilePath.Text = ofd.FileName;
}

/// <summary>
/// 發送文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSendFiles_Click(object sender, EventArgs e)
{
if (cboUsers.Text.Equals(""))//判斷是否選擇了客戶端ip地址
{
MessageBox.Show("請選擇客戶端ip地址", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
if (txtFilePath.Text.Equals(""))//判讀是否選擇了文件路徑
{
MessageBox.Show("請選擇文件路徑", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
//獲取發送文件的路徑
string path = txtFilePath.Text;
using (FileStream fsRead = new FileStream(path, FileMode.Open, FileAccess.Read))
{
byte[] buf = new byte[5 * 1024 * 1024];
int r = fsRead.Read(buf, 0, buf.Length);
List<byte> list = new List<byte>();
list.Add(1);
list.AddRange(buf);
byte[] newBuffer = list.ToArray();
//發送字節數組給指定客戶端
dicSocket[cboUsers.SelectedItem.ToString()].Send(newBuffer, 0, r + 1, SocketFlags.None);
}
}

}

}
#endregion

#region 服務器向客戶端發送震動
/// <summary>
/// 服務器向客戶端發送震動
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSnake_Click(object sender, EventArgs e)
{
if (cboUsers.Text.Equals(""))//判斷是否選擇了客戶端ip地址
{
MessageBox.Show("請選擇客戶端ip地址", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
byte[] buffer = new byte[1];
buffer[0] = 2;
dicSocket[cboUsers.SelectedItem.ToString()].Send(buffer);
}

}
#endregion

#region 鼠標點擊清除提示文字
/// <summary>
/// 鼠標點擊清除提示文字
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void txtMessage_mouseDown(object sender, MouseEventArgs e)
{
this.txtMessage.Text = "";
}
#endregion

private void Form1_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;//取消跨線程檢測
Form2 f2 = new Form2();
f2.Show();
}

 

這是客戶端的頁面

//創建負責通信的socket
Socket sendSocket;

#region 接收服務器端發來的消息
private void btnStart_Click(object sender, EventArgs e)
{
if (txtIp.Text.Equals("") || txtPort.Text.Equals(""))//判讀是否輸入了ip地址和端口號
{
MessageBox.Show("請輸入ip地址和端口號", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
try
{
sendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Parse(txtIp.Text);
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));
//獲取遠程服務器的ip地址和端口號
sendSocket.Connect(point);
ShowMsg("連接成功");
//開啟一個新的線程不停的接受服務器發來的消息
Thread th = new Thread(Receive);
th.IsBackground = true;
th.Start();
}
catch
{


}
}

}
/// <summary>
/// 不停接收服務器發來的消息
/// </summary>
private void Receive()
{
while (true)
{
try
{
byte[] buffer = new byte[1024 * 1024 * 3];
int r = sendSocket.Receive(buffer);//實時接收有效字節數
if (r==0)
{
break;
}
//接收的是文字消息
if (buffer[0]==0)
{
string str = Encoding.UTF8.GetString(buffer, 1, r - 1);//從下標為1的開始解析r-1個
ShowMsg(sendSocket.RemoteEndPoint + ";" + str);
}
//接收的是文件
else if (buffer[0]==1)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Title = "請選擇保持路徑";
sfd.InitialDirectory = @"C:\Users\Public\Pictures\Sample Pictures";
sfd.Filter = "所有文件|*.*";
sfd.ShowDialog(this);
string path = sfd.FileName;
using (FileStream fsWrite = new FileStream(path,FileMode.Open,FileAccess.Write))
{
fsWrite.Write(buffer, 1, r - 1);
}
MessageBox.Show("保存成功");
}
//震動接收
else if (buffer[0]==2)
{
shake();
}
}
catch
{


}
}
}
/// <summary>
/// 震動方法
/// </summary>
private void shake()
{
for (int i = 0; i < 500; i++)
{
this.Location = new Point(200, 300);
this.Location = new Point(300, 300);
}
}

private void ShowMsg(string str)
{
txtLog.AppendText(str + "\r\n");
}
#endregion

#region 向服務器發送消息
/// <summary>
/// 向服務器發送消息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSendMessage_Click(object sender, EventArgs e)
{
if (txtMessage.Text.Equals(""))//判讀是否填寫發送消息
{
MessageBox.Show("請輸入要發送的信息", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else
{
string str = txtMessage.Text.Trim();
byte[] buf = Encoding.UTF8.GetBytes(str);
//發送消息
sendSocket.Send(buf);
txtMessage.Text = null;
}

}
#endregion

#region 鼠標點擊清除提示文字
/// <summary>
/// 鼠標點擊清除提示文字
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void txtMessage_mouseDown(object sender, MouseEventArgs e)
{
this.txtMessage.Text = "";
}
#endregion

private void Form2_Load(object sender, EventArgs e)
{
Control.CheckForIllegalCrossThreadCalls = false;//取消跨線程檢查
}

下面是執行順序

1.首先在服務器端輸入ip地址以及端口號,點擊開始監聽,

然后在客戶端輸入相應的ip地址以及端口號,點擊連接。(通過如圖)

2.在服務器端的下拉選擇框選擇客戶端ip地址與端口號(注意如果不選擇,發送消息,震動以及發送文件功能無法實現,如圖)

一下的操作就簡單了,客戶端可以向服務器端發送消息,服務器端也能向客戶端發送相應的動作(如圖)


免責聲明!

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



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