C# winfroms使用socket客戶端服務(wù)端的示例代碼
C# winfroms使用socket客戶端服務(wù)端代碼詳解,聲明Socket 第一個參數(shù):尋址方式,第二個參數(shù):傳輸數(shù)據(jù)的方式,第三個參數(shù):通信協(xié)議Socket socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); 開啟偵聽 參數(shù)是指可以連接的客戶端數(shù)量socket.Listen(10);,socket.Accept();這里需要注意,Accept()會阻塞線程,直到連接上客戶端。如果放在主線程中,會阻塞前臺操作。需要創(chuàng)建一個新的線程。Accept()返回一個socket,客戶端連接上之后,服務(wù)端自動生成一個socket和連接的客端通信。連接成功后,向客戶端發(fā)送“連接成功!”
1.通信相關(guān)說明
1.1服務(wù)端與客戶端
啟動服務(wù)端后,服務(wù)端通過持續(xù)監(jiān)聽客戶端發(fā)來的請求,一旦監(jiān)聽到客戶端傳來的信息(請求),兩端便可以互發(fā)信息了.
服務(wù)端需要綁定一個IP,用于客戶端在網(wǎng)絡(luò)中尋找并建立連接(支持局域網(wǎng)內(nèi)部客戶端與服務(wù)端之間的互相通信)
1.2 信息發(fā)送原理
將手動輸入字符串信息轉(zhuǎn)換成機(jī)器可以識別的字節(jié)數(shù)組,然后調(diào)用套接字的Send()方法將字節(jié)數(shù)組發(fā)送出去
1.3 信息接收原理
調(diào)用套接字的Receive()方法,獲取對端傳來的字節(jié)數(shù)組,然后將其轉(zhuǎn)換成人可以讀懂的字符串信息
2.socket代碼
2.1 客戶端代碼
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace TcpMsgClient { public partial class FrmClient : Form { public FrmClient() { InitializeComponent(); //關(guān)閉對文本框的非法線程操作檢查 TextBox.CheckForIllegalCrossThreadCalls = false; } //創(chuàng)建 1個客戶端套接字 和1個負(fù)責(zé)監(jiān)聽服務(wù)端請求的線程 Socket socketClient = null; Thread threadClient = null; /// <summary> /// 連接服務(wù)端事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnListenServer_Click(object sender, EventArgs e) { //定義一個套字節(jié)監(jiān)聽 包含3個參數(shù)(IP4尋址協(xié)議,流式連接,TCP協(xié)議) socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //需要獲取文本框中的IP地址 IPAddress ipaddress = IPAddress.Parse(this.txtIP.Text.Trim()); //將獲取的ip地址和端口號綁定到網(wǎng)絡(luò)節(jié)點endpoint上 IPEndPoint endpoint = new IPEndPoint(ipaddress, int.Parse(this.txtPort.Text.Trim())); //這里客戶端套接字連接到網(wǎng)絡(luò)節(jié)點(服務(wù)端)用的方法是Connect 而不是Bind try { socketClient.Connect(endpoint); this.txtMsg.AppendText("客戶端連接服務(wù)端成功!" + "\r\n"); this.btnListenServer.Enabled = false; //創(chuàng)建一個線程 用于監(jiān)聽服務(wù)端發(fā)來的消息 threadClient = new Thread(RecMsg); //將窗體線程設(shè)置為與后臺同步 threadClient.IsBackground = true; //啟動線程 threadClient.Start(); } catch (Exception ex) { this.txtMsg.AppendText("遠(yuǎn)程服務(wù)端斷開,連接失敗!" + "\r\n"); } } /// <summary> /// 接收服務(wù)端發(fā)來信息的方法 /// </summary> private void RecMsg() { while (true) //持續(xù)監(jiān)聽服務(wù)端發(fā)來的消息 { try { //定義一個1M的內(nèi)存緩沖區(qū) 用于臨時性存儲接收到的信息 byte[] arrRecMsg = new byte[1024 * 1024]; //將客戶端套接字接收到的數(shù)據(jù)存入內(nèi)存緩沖區(qū), 并獲取其長度 int length = socketClient.Receive(arrRecMsg); //將套接字獲取到的字節(jié)數(shù)組轉(zhuǎn)換為人可以看懂的字符串 string strRecMsg = Encoding.UTF8.GetString(arrRecMsg, 0, length); //將發(fā)送的信息追加到聊天內(nèi)容文本框中 txtMsg.AppendText("服務(wù)端 " + GetCurrentTime() + "\r\n" + strRecMsg + "\r\n"); } catch (Exception ex) { this.txtMsg.AppendText("遠(yuǎn)程服務(wù)器已中斷連接!"+"\r\n"); this.btnListenServer.Enabled = true; break; } } } /// <summary> /// 發(fā)送字符串信息到服務(wù)端的方法 /// </summary> /// <param name="sendMsg">發(fā)送的字符串信息</param> private void ClientSendMsg(string sendMsg) { try { //將輸入的內(nèi)容字符串轉(zhuǎn)換為機(jī)器可以識別的字節(jié)數(shù)組 byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(sendMsg); //調(diào)用客戶端套接字發(fā)送字節(jié)數(shù)組 socketClient.Send(arrClientSendMsg); //將發(fā)送的信息追加到聊天內(nèi)容文本框中 txtMsg.AppendText("天涯 " + GetCurrentTime() + "\r\n" + sendMsg + "\r\n"); } catch(Exception ex){ this.txtMsg.AppendText("遠(yuǎn)程服務(wù)器已中斷連接,無法發(fā)送消息!" + "\r\n"); } } private void btnSendMsg_Click(object sender, EventArgs e) { //調(diào)用ClientSendMsg方法 將文本框中輸入的信息發(fā)送給服務(wù)端 ClientSendMsg(this.txtClientSendMsg.Text.Trim()); this.txtClientSendMsg.Clear(); } private void txtClientSendMsg_KeyDown(object sender, KeyEventArgs e) { //當(dāng)光標(biāo)位于文本框時 如果用戶按下了鍵盤上的Enter鍵 if (e.KeyCode == Keys.Enter) { //則調(diào)用客戶端向服務(wù)端發(fā)送信息的方法 ClientSendMsg(this.txtClientSendMsg.Text.Trim()); this.txtClientSendMsg.Clear(); } } /// <summary> /// 獲取當(dāng)前系統(tǒng)時間的方法 /// </summary> /// <returns>當(dāng)前時間</returns> private DateTime GetCurrentTime() { DateTime currentTime = new DateTime(); currentTime = DateTime.Now; return currentTime; } } }
2.2 服務(wù)端代碼
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace TcpMsgServer { public partial class FrmServer : Form { public FrmServer() { InitializeComponent(); //關(guān)閉對文本框的非法線程操作檢查 TextBox.CheckForIllegalCrossThreadCalls = false; } Thread threadWatch = null; //負(fù)責(zé)監(jiān)聽客戶端的線程 Socket socketWatch = null; //負(fù)責(zé)監(jiān)聽客戶端的套接字 /// <summary> /// 啟動服務(wù) /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnServerConn_Click(object sender, EventArgs e) { try { //定義一個套接字用于監(jiān)聽客戶端發(fā)來的信息 包含3個參數(shù)(IP4尋址協(xié)議,流式連接,TCP協(xié)議) socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //服務(wù)端發(fā)送信息 需要1個IP地址和端口號 IPAddress ipaddress = IPAddress.Parse(this.txtIP.Text.Trim()); //獲取文本框輸入的IP地址 //將IP地址和端口號綁定到網(wǎng)絡(luò)節(jié)點endpoint上 IPEndPoint endpoint = new IPEndPoint(ipaddress, int.Parse(this.txtPort.Text.Trim())); //獲取文本框上輸入的端口號 //監(jiān)聽綁定的網(wǎng)絡(luò)節(jié)點 socketWatch.Bind(endpoint); //將套接字的監(jiān)聽隊列長度限制為20 socketWatch.Listen(20); //創(chuàng)建一個監(jiān)聽線程 threadWatch = new Thread(WatchConnecting); //將窗體線程設(shè)置為與后臺同步 threadWatch.IsBackground = true; //啟動線程 threadWatch.Start(); //啟動線程后 txtMsg文本框顯示相應(yīng)提示 txtMsg.AppendText("開始監(jiān)聽客戶端傳來的信息!" + "\r\n"); this.btnServerConn.Enabled = false; } catch (Exception ex) { txtMsg.AppendText("服務(wù)端啟動服務(wù)失敗!" + "\r\n"); this.btnServerConn.Enabled = true; } } //創(chuàng)建一個負(fù)責(zé)和客戶端通信的套接字 Socket socConnection = null; /// <summary> /// 監(jiān)聽客戶端發(fā)來的請求 /// </summary> private void WatchConnecting() { while (true) //持續(xù)不斷監(jiān)聽客戶端發(fā)來的請求 { socConnection = socketWatch.Accept(); txtMsg.AppendText("客戶端連接成功! " + "\r\n"); //創(chuàng)建一個通信線程 ParameterizedThreadStart pts = new ParameterizedThreadStart(ServerRecMsg); Thread thr = new Thread(pts); thr.IsBackground = true; //啟動線程 thr.Start(socConnection); } } /// <summary> /// 發(fā)送信息到客戶端的方法 /// </summary> /// <param name="sendMsg">發(fā)送的字符串信息</param> private void ServerSendMsg(string sendMsg) { try { //將輸入的字符串轉(zhuǎn)換成 機(jī)器可以識別的字節(jié)數(shù)組 byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendMsg); //向客戶端發(fā)送字節(jié)數(shù)組信息 socConnection.Send(arrSendMsg); //將發(fā)送的字符串信息附加到文本框txtMsg上 txtMsg.AppendText("服務(wù)器 " + GetCurrentTime() + "\r\n" + sendMsg + "\r\n"); } catch (Exception ex) { txtMsg.AppendText("客戶端已斷開連接,無法發(fā)送信息!" + "\r\n"); } } /// <summary> /// 接收客戶端發(fā)來的信息 /// </summary> /// <param name="socketClientPara">客戶端套接字對象</param> private void ServerRecMsg(object socketClientPara) { Socket socketServer = socketClientPara as Socket; while (true) { //創(chuàng)建一個內(nèi)存緩沖區(qū) 其大小為1024*1024字節(jié) 即1M byte[] arrServerRecMsg = new byte[1024 * 1024]; try { //將接收到的信息存入到內(nèi)存緩沖區(qū),并返回其字節(jié)數(shù)組的長度 int length = socketServer.Receive(arrServerRecMsg); //將機(jī)器接受到的字節(jié)數(shù)組轉(zhuǎn)換為人可以讀懂的字符串 string strSRecMsg = Encoding.UTF8.GetString(arrServerRecMsg, 0, length); //將發(fā)送的字符串信息附加到文本框txtMsg上 txtMsg.AppendText("天涯 " + GetCurrentTime() + "\r\n" + strSRecMsg + "\r\n"); } catch (Exception ex) { txtMsg.AppendText("客戶端已斷開連接!" + "\r\n"); break; } } } /// <summary> /// 發(fā)送消息到客戶端 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSendMsg_Click(object sender, EventArgs e) { //調(diào)用 ServerSendMsg方法 發(fā)送信息到客戶端 ServerSendMsg(this.txtSendMsg.Text.Trim()); this.txtSendMsg.Clear(); } /// <summary> /// 快捷鍵 Enter 發(fā)送信息 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void txtSendMsg_KeyDown(object sender, KeyEventArgs e) { //如果用戶按下了Enter鍵 if (e.KeyCode == Keys.Enter) { //則調(diào)用 服務(wù)器向客戶端發(fā)送信息的方法 ServerSendMsg(txtSendMsg.Text.Trim()); this.txtSendMsg.Clear(); } } /// <summary> /// 獲取當(dāng)前系統(tǒng)時間的方法 /// </summary> /// <returns>當(dāng)前時間</returns> private DateTime GetCurrentTime() { DateTime currentTime = new DateTime(); currentTime = DateTime.Now; return currentTime; } /// <summary> /// 獲取本地IPv4地址 /// </summary> /// <returns></returns> public IPAddress GetLocalIPv4Address() { IPAddress localIpv4 = null; //獲取本機(jī)所有的IP地址列表 IPAddress[] IpList = Dns.GetHostAddresses(Dns.GetHostName()); //循環(huán)遍歷所有IP地址 foreach (IPAddress IP in IpList) { //判斷是否是IPv4地址 if (IP.AddressFamily == AddressFamily.InterNetwork) { localIpv4 = IP; } else { continue; } } return localIpv4; } /// <summary> /// 獲取本地IP事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnGetLocalIP_Click(object sender, EventArgs e) { //接收IPv4的地址 IPAddress localIP = GetLocalIPv4Address(); //賦值給文本框 this.txtIP.Text = localIP.ToString(); } } }
3.定時任務(wù)處理報文
Timers定時任務(wù)
在內(nèi)部多線程情況下,這個定時任務(wù),支持,啟動,設(shè)定條件,滿足后執(zhí)行任務(wù),不滿做執(zhí)行設(shè)定任務(wù),然后自動銷毀。
using SimulateMaster.Bean; using SimulateMaster.page; using Sunny.UI; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Timers; namespace SimulateMaster.Util { public class MsgReply { private ServiceMain _serviceMain; private readonly System.Timers.Timer _timer; public static string clicentInfo_value = ""; //設(shè)備信息【IP:端口】 public static string mainName_value=""; //窗體名稱 public static string msgContent= MsgUtils.MSG_QDLL;//報文內(nèi)容 public int msgNum=0;//重發(fā)次數(shù) 最多三次 public MsgReply(string msgValue,string clientInfo,string mainName, ServiceMain serviceMain) { clicentInfo_value = clientInfo; mainName_value = mainName; _serviceMain = serviceMain; msgContent = msgValue; // 設(shè)置定時器間隔(單位為毫秒) _timer = new System.Timers.Timer(5000); // 添加 Elapsed 事件處理程序 _timer.Elapsed += OnTimerElapsed; // 開始計時器 _timer.Start(); } protected virtual void OnTimerElapsed(object sender, ElapsedEventArgs e) { FileUtils.WriteFileLog("定時任務(wù)觸發(fā)沒有接收到回復(fù)報文!", "報文接收定時任務(wù)"); } public void Dispose() { FileUtils.WriteFileLog(clicentInfo_value + "定時任務(wù)關(guān)閉!", "報文接收定時任務(wù)"); if (_timer != null && _timer.Enabled) _timer.Stop(); _timer?.Dispose(); } } }
到此這篇關(guān)于C# winfroms使用socket客戶端服務(wù)端的示例代碼的文章就介紹到這了,更多相關(guān)C# socket客戶端服務(wù)端內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#線程 BeginInvoke和EndInvoke使用方法
本文開始C#線程系列講座之一,即BeginInvoke和EndInvoke的使用方法,需要的朋友可以參考下2013-05-05C# JavaScriptSerializer序列化時的時間處理詳解
這篇文章主要為大家詳細(xì)介紹了C# JavaScriptSerializer序列化時的時間處理詳解,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08