C# winfroms使用socket客戶端服務端的示例代碼
C# winfroms使用socket客戶端服務端代碼詳解,聲明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,客戶端連接上之后,服務端自動生成一個socket和連接的客端通信。連接成功后,向客戶端發(fā)送“連接成功!”
1.通信相關說明
1.1服務端與客戶端
啟動服務端后,服務端通過持續(xù)監(jiān)聽客戶端發(fā)來的請求,一旦監(jiān)聽到客戶端傳來的信息(請求),兩端便可以互發(fā)信息了.
服務端需要綁定一個IP,用于客戶端在網(wǎng)絡中尋找并建立連接(支持局域網(wǎng)內部客戶端與服務端之間的互相通信)
1.2 信息發(fā)送原理
將手動輸入字符串信息轉換成機器可以識別的字節(jié)數(shù)組,然后調用套接字的Send()方法將字節(jié)數(shù)組發(fā)送出去
1.3 信息接收原理
調用套接字的Receive()方法,獲取對端傳來的字節(jié)數(shù)組,然后將其轉換成人可以讀懂的字符串信息
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();
//關閉對文本框的非法線程操作檢查
TextBox.CheckForIllegalCrossThreadCalls = false;
}
//創(chuàng)建 1個客戶端套接字 和1個負責監(jiān)聽服務端請求的線程
Socket socketClient = null;
Thread threadClient = null;
/// <summary>
/// 連接服務端事件
/// </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)絡節(jié)點endpoint上
IPEndPoint endpoint = new IPEndPoint(ipaddress, int.Parse(this.txtPort.Text.Trim()));
//這里客戶端套接字連接到網(wǎng)絡節(jié)點(服務端)用的方法是Connect 而不是Bind
try
{
socketClient.Connect(endpoint);
this.txtMsg.AppendText("客戶端連接服務端成功!" + "\r\n");
this.btnListenServer.Enabled = false;
//創(chuàng)建一個線程 用于監(jiān)聽服務端發(fā)來的消息
threadClient = new Thread(RecMsg);
//將窗體線程設置為與后臺同步
threadClient.IsBackground = true;
//啟動線程
threadClient.Start();
}
catch (Exception ex) {
this.txtMsg.AppendText("遠程服務端斷開,連接失?。? + "\r\n");
}
}
/// <summary>
/// 接收服務端發(fā)來信息的方法
/// </summary>
private void RecMsg()
{
while (true) //持續(xù)監(jiān)聽服務端發(fā)來的消息
{
try
{
//定義一個1M的內存緩沖區(qū) 用于臨時性存儲接收到的信息
byte[] arrRecMsg = new byte[1024 * 1024];
//將客戶端套接字接收到的數(shù)據(jù)存入內存緩沖區(qū), 并獲取其長度
int length = socketClient.Receive(arrRecMsg);
//將套接字獲取到的字節(jié)數(shù)組轉換為人可以看懂的字符串
string strRecMsg = Encoding.UTF8.GetString(arrRecMsg, 0, length);
//將發(fā)送的信息追加到聊天內容文本框中
txtMsg.AppendText("服務端 " + GetCurrentTime() + "\r\n" + strRecMsg + "\r\n");
}
catch (Exception ex) {
this.txtMsg.AppendText("遠程服務器已中斷連接!"+"\r\n");
this.btnListenServer.Enabled = true;
break;
}
}
}
/// <summary>
/// 發(fā)送字符串信息到服務端的方法
/// </summary>
/// <param name="sendMsg">發(fā)送的字符串信息</param>
private void ClientSendMsg(string sendMsg)
{
try {
//將輸入的內容字符串轉換為機器可以識別的字節(jié)數(shù)組
byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(sendMsg);
//調用客戶端套接字發(fā)送字節(jié)數(shù)組
socketClient.Send(arrClientSendMsg);
//將發(fā)送的信息追加到聊天內容文本框中
txtMsg.AppendText("天涯 " + GetCurrentTime() + "\r\n" + sendMsg + "\r\n");
}
catch(Exception ex){
this.txtMsg.AppendText("遠程服務器已中斷連接,無法發(fā)送消息!" + "\r\n");
}
}
private void btnSendMsg_Click(object sender, EventArgs e)
{
//調用ClientSendMsg方法 將文本框中輸入的信息發(fā)送給服務端
ClientSendMsg(this.txtClientSendMsg.Text.Trim());
this.txtClientSendMsg.Clear();
}
private void txtClientSendMsg_KeyDown(object sender, KeyEventArgs e)
{
//當光標位于文本框時 如果用戶按下了鍵盤上的Enter鍵
if (e.KeyCode == Keys.Enter)
{
//則調用客戶端向服務端發(fā)送信息的方法
ClientSendMsg(this.txtClientSendMsg.Text.Trim());
this.txtClientSendMsg.Clear();
}
}
/// <summary>
/// 獲取當前系統(tǒng)時間的方法
/// </summary>
/// <returns>當前時間</returns>
private DateTime GetCurrentTime()
{
DateTime currentTime = new DateTime();
currentTime = DateTime.Now;
return currentTime;
}
}
}
2.2 服務端代碼
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();
//關閉對文本框的非法線程操作檢查
TextBox.CheckForIllegalCrossThreadCalls = false;
}
Thread threadWatch = null; //負責監(jiān)聽客戶端的線程
Socket socketWatch = null; //負責監(jiān)聽客戶端的套接字
/// <summary>
/// 啟動服務
/// </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);
//服務端發(fā)送信息 需要1個IP地址和端口號
IPAddress ipaddress = IPAddress.Parse(this.txtIP.Text.Trim()); //獲取文本框輸入的IP地址
//將IP地址和端口號綁定到網(wǎng)絡節(jié)點endpoint上
IPEndPoint endpoint = new IPEndPoint(ipaddress, int.Parse(this.txtPort.Text.Trim())); //獲取文本框上輸入的端口號
//監(jiān)聽綁定的網(wǎng)絡節(jié)點
socketWatch.Bind(endpoint);
//將套接字的監(jiān)聽隊列長度限制為20
socketWatch.Listen(20);
//創(chuàng)建一個監(jiān)聽線程
threadWatch = new Thread(WatchConnecting);
//將窗體線程設置為與后臺同步
threadWatch.IsBackground = true;
//啟動線程
threadWatch.Start();
//啟動線程后 txtMsg文本框顯示相應提示
txtMsg.AppendText("開始監(jiān)聽客戶端傳來的信息!" + "\r\n");
this.btnServerConn.Enabled = false;
}
catch (Exception ex) {
txtMsg.AppendText("服務端啟動服務失敗!" + "\r\n");
this.btnServerConn.Enabled = true;
}
}
//創(chuàng)建一個負責和客戶端通信的套接字
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
{
//將輸入的字符串轉換成 機器可以識別的字節(jié)數(shù)組
byte[] arrSendMsg = Encoding.UTF8.GetBytes(sendMsg);
//向客戶端發(fā)送字節(jié)數(shù)組信息
socConnection.Send(arrSendMsg);
//將發(fā)送的字符串信息附加到文本框txtMsg上
txtMsg.AppendText("服務器 " + 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)建一個內存緩沖區(qū) 其大小為1024*1024字節(jié) 即1M
byte[] arrServerRecMsg = new byte[1024 * 1024];
try
{
//將接收到的信息存入到內存緩沖區(qū),并返回其字節(jié)數(shù)組的長度
int length = socketServer.Receive(arrServerRecMsg);
//將機器接受到的字節(jié)數(shù)組轉換為人可以讀懂的字符串
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)
{
//調用 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)
{
//則調用 服務器向客戶端發(fā)送信息的方法
ServerSendMsg(txtSendMsg.Text.Trim());
this.txtSendMsg.Clear();
}
}
/// <summary>
/// 獲取當前系統(tǒng)時間的方法
/// </summary>
/// <returns>當前時間</returns>
private DateTime GetCurrentTime()
{
DateTime currentTime = new DateTime();
currentTime = DateTime.Now;
return currentTime;
}
/// <summary>
/// 獲取本地IPv4地址
/// </summary>
/// <returns></returns>
public IPAddress GetLocalIPv4Address() {
IPAddress localIpv4 = null;
//獲取本機所有的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.定時任務處理報文
Timers定時任務
在內部多線程情況下,這個定時任務,支持,啟動,設定條件,滿足后執(zhí)行任務,不滿做執(zhí)行設定任務,然后自動銷毀。
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 = ""; //設備信息【IP:端口】
public static string mainName_value=""; //窗體名稱
public static string msgContent= MsgUtils.MSG_QDLL;//報文內容
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;
// 設置定時器間隔(單位為毫秒)
_timer = new System.Timers.Timer(5000);
// 添加 Elapsed 事件處理程序
_timer.Elapsed += OnTimerElapsed;
// 開始計時器
_timer.Start();
}
protected virtual void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
FileUtils.WriteFileLog("定時任務觸發(fā)沒有接收到回復報文!", "報文接收定時任務");
}
public void Dispose()
{
FileUtils.WriteFileLog(clicentInfo_value + "定時任務關閉!", "報文接收定時任務");
if (_timer != null && _timer.Enabled)
_timer.Stop();
_timer?.Dispose();
}
}
}到此這篇關于C# winfroms使用socket客戶端服務端的示例代碼的文章就介紹到這了,更多相關C# socket客戶端服務端內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C#線程 BeginInvoke和EndInvoke使用方法
本文開始C#線程系列講座之一,即BeginInvoke和EndInvoke的使用方法,需要的朋友可以參考下2013-05-05
C# JavaScriptSerializer序列化時的時間處理詳解
這篇文章主要為大家詳細介紹了C# JavaScriptSerializer序列化時的時間處理詳解,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08

