這次寫一下Socket客戶端,
在此之前先分享一下我找到的一張圖
這張圖和之前我畫的服務器端和客戶端之間的通信基本相同,不過這張圖更可信一點。
下面就來寫一下左面的客戶端
下面直接貼代碼了
public MainFrm()
{
InitializeComponent();
}
private Socket socket;
private void btnConn_Click(object sender, EventArgs e)
{
//創建一個Socket對象
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
txtMsgShow("正在努力鏈接服務器端。。。。");
//等待期間需要處理異常
try
{
//連接服務器
clientSocket.Connect(IPAddress.Parse(txtIP.Text), int.Parse(txtPort.Text));
}
catch (Exception)
{
Thread.Sleep(3000);
MessageBox.Show("連接失敗!請重新連接。。。");
return;
}
socket = clientSocket;
txtMsgShow(string.Format("{0}服務器端已經連接成功\r\n",socket.RemoteEndPoint));
//開啓另一個線程接收數據
ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveMsgFromServer), socket);
}
//接收數據
private void ReceiveMsgFromServer(object state)
{
Socket socket = (Socket)state;
int count=0;
//1M緩存區
byte[] recByte = new byte[1024 * 1024];
while (true)
{
try
{
count = socket.Receive(recByte, 0, recByte.Length, SocketFlags.None);
}
catch
{
txtMsgShow(string.Format("來自服務器端的消息:對方非正常退出了\r\n{0}", txtMsg.Text));
StopConnect();
return;
}
//判斷一下服務器端是否正常退出
//正常退出
if (count <= 0)
{
txtMsgShow(string.Format("來自服務器端的消息:對方正常退出了{0}",txtMsg.Text));
StopConnect();
return;
}
//然後將緩存區中的byte轉換成string在msg中顯示出來
string str = Encoding.Default.GetString(recByte, 0, count);
txtMsgShow(string.Format("來自服務器端的消息:{1}\r\n{0}", txtMsg.Text, str));
}
}
//發送數據
private void btnSend_Click(object sender, EventArgs e)
{
if (socket.Connected)
{
byte[] sendByte = Encoding.Default.GetBytes(txtSend.Text);
socket.Send(sendByte,0,sendByte.Length,SocketFlags.None);
txtMsgShow(string.Format("你發送的消息:{0}\r\n{1}", txtSend.Text,txtMsg.Text));
//清空發送欄
txtSend.Text = "";
}
}
//用於顯示接收連接情況
private void txtMsgShow(string str)
{
if (txtMsg.InvokeRequired)
{
txtMsg.Invoke(new Action<string>((s) => {
txtMsg.Text = s;
}),str);
}
else
{
txtMsg.Text = str;
}
}
//關閉連接
private void StopConnect()
{
try
{
if (socket.Connected)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close(100);
}
}
//不管了
catch
{
}
}
private void MainFrm_FormClosing(object sender, FormClosingEventArgs e)
{
StopConnect();
}
}
這裏有兩點需要注意:
(1)客戶端的Socket會自動分配一個隨機的端口,所以在IP一欄填服務器主機的IP就行
(2)如果你是調試進行的測試,在關閉客戶端時,會報一個創建句柄出錯的異常,
是這句話的異常
txtMsgShow(string.Format("來自服務器端的消息:對方非正常退出了\r\n{0}", txtMsg.Text));
因爲你已經關閉窗體,所以不可能再在txtbox中顯示消息。
不過你可以不用理會這個異常,因爲,真正使用exe時,窗體已經關閉,不可能再有什麼異常。
結合之前寫過的服務器端就可以互相通信了。