TCP最主要的特點如下。
(1) 是面向連接配接的協定。
(2) 端到端的通信。每個TCP連接配接隻能有兩個端點,而且隻能一對一通信,不能一點對多點直接通信。
(3) 高可靠性。通過TCP連接配接傳送的資料,能保證資料無差錯、不丢失、不重複地準确到達接收方,并且保證各資料到達的順序與其發出的順序相同
異步與同步的差別
同步工作方式是指利用TCP編寫的程式執行到監聽或接收語句時,在未完成工作(偵聽到連接配接請求或收到對方發來的資料)前不再繼續往下執行,線程處于阻塞狀态,直到該語句完成相應的工作後才繼續執行下一條語句。
異步工作方式是指程式執行到監聽或接收語句時,不論工作是否完成,都會繼續往下執行
完整源碼如下:
public partial class MainForm : Form
{
private Socket socket;
//Thread threadConnect;
private int sendCount = 0;
private int receiveCount = 0;
/*------------定義與聲明委托------------*/
//顯示消息
private delegate void ShowMsgCallBack(string str);
private ShowMsgCallBack showMsgCallBack;
//顯示狀态
private delegate void ShowStatusInfoCallBack(string str);
private ShowStatusInfoCallBack showStatusInfoCallBack;
//顯示發送計數
private delegate void ShowSendCountCallBack(string str);
private ShowSendCountCallBack showSendCountCallBack;
//顯示接收計數
private delegate void ShowReceiveCountCallBack(string str);
private ShowReceiveCountCallBack showReceiveCountCallBack;
//定時重連
private delegate void ReConnectCallBack();
private ReConnectCallBack reConnectCallBack;
//異步調用(與要調用的方法具有相同簽名)
private delegate void ReceiveMsgDelegate(out string receiveMsg);
private ReceiveMsgDelegate receiveMsgDelegate;
private delegate void SendMsgDelegate(string sendMsg);
private SendMsgDelegate sendMsgDelegate;
/*------------定義與聲明委托------------*/
public MainForm()
{
InitializeComponent();
/*----------執行個體化委托----------*/
//顯示消息
showMsgCallBack = new ShowMsgCallBack(ShowMsg);
//顯示狀态
showStatusInfoCallBack = new ShowStatusInfoCallBack(ShowStatusInfo);
//顯示發送計數
showSendCountCallBack = new ShowSendCountCallBack(ShowSendCount);
//顯示接收計數
showReceiveCountCallBack = new ShowReceiveCountCallBack(ShowReceiveCount);
//掉線後自動啟動定時重連
reConnectCallBack = new ReConnectCallBack(ReConnect);
//接收消息
receiveMsgDelegate = new ReceiveMsgDelegate(AsyncRcvMsg);
//發送消息
sendMsgDelegate = new SendMsgDelegate(AsyncSendMsg);
/*----------執行個體化委托----------*/
IPAddress[] localIP = Dns.GetHostAddresses("");
txtIP.Text = localIP[0].ToString();
txtIP.SelectAll();
txtPort.Text = "9501";
tbxReceiveCount.Text = sendCount.ToString();
tbxReceiveCount.Text = receiveCount.ToString();
}
/*----------定義回調函數----------*/
//顯示消息
private void ShowMsg(string str)
{
lstBoxMsg.Items.Add(str);
lstBoxMsg.TopIndex = lstBoxMsg.Items.Count - 1;
}
//顯示狀态
private void ShowStatusInfo(string str)
{
toolStripStatusInfo.Text = str;
}
//顯示發送計數
private void ShowSendCount(string str)
{
tbxSendCount.Text = str;
}
//顯示接收計數
private void ShowReceiveCount(string str)
{
tbxReceiveCount.Text = str;
}
private void ReConnect()
{
startConnectServer();
}
//異步接收
private void AsyncRcvMsg(out string receiveMessage)
{
receiveMessage = null;
try
{
Byte[] receiveByte = new Byte[64];
socket.Receive(receiveByte, receiveByte.Length, 0);
receiveMessage = Encoding.ASCII.GetString(receiveByte);
if (receiveMessage.Trim('\0').Length == 0)
{
if (socket != null)
{
socket.Close();
}
statusStripInfo.Invoke(showStatusInfoCallBack, "異步接收時連接配接斷開!延時10秒後自動重新連接配接...");
//延時10秒後重新連接配接
DateTime now = DateTime.Now;
while (now.AddSeconds(10) > DateTime.Now) { }
Invoke(reConnectCallBack);
}
}
catch
{
if (socket != null)
{
socket.Close();
}
statusStripInfo.Invoke(showStatusInfoCallBack, "異步接收時發生異常,連接配接斷開!延時10秒後自動重新連接配接...");
//延時10秒後重新連接配接
DateTime now = DateTime.Now;
while (now.AddSeconds(10) > DateTime.Now) { }
Invoke(reConnectCallBack);
}
}
//異步發送
private void AsyncSendMsg(string sendMessage)
{
try
{
Byte[] sendByte = new Byte[64];
sendByte = Encoding.ASCII.GetBytes(sendMessage.ToCharArray());
socket.Send(sendByte, sendByte.Length, 0);
}
catch
{
if (socket != null)
{
socket.Close();
}
statusStripInfo.Invoke(showStatusInfoCallBack, "異步發送時異常,連接配接斷開!");
}
}
//定義回調函數
private void btnConnect_Click(object sender, EventArgs e)
{
startConnectServer();
}
private void startConnectServer()
{
Thread threadConnect = new Thread(ConnectServerThread);
threadConnect.Start();
btnConnect.Enabled = false;
btnSend.Enabled = true;
btnDisConnect.Enabled = true;
}
//發起連接配接請求
private void ConnectServerThread()
{
statusStripInfo.Invoke(showStatusInfoCallBack, "正在連接配接……");
AsyncCallback requestcallback = new AsyncCallback(RequestCallBack);
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult result = socket.BeginConnect(IPAddress.Parse(txtIP.Text), int.Parse(txtPort.Text), requestcallback, socket);
while (result.IsCompleted == false)
{
Thread.Sleep(30);
}
}
//回調函數,用于向服務程序發起連接配接請求
private void RequestCallBack(IAsyncResult iar)
{
try
{
socket = (Socket)iar.AsyncState;
socket.EndConnect(iar);
if (socket != null)
{
statusStripInfo.Invoke(showStatusInfoCallBack, "Socket連接配接成功!");
Thread threadReceive = new Thread(ReceiveMessage);
threadReceive.Start();
}
}
catch
{
statusStripInfo.Invoke(showStatusInfoCallBack, "Socket連接配接時異常連接配接失敗!延時10秒後自動重新連接配接...");
//延時10秒後重新連接配接
DateTime now = DateTime.Now;
while (now.AddSeconds(10) > DateTime.Now) { }
Invoke(reConnectCallBack);
}
}
//接收消息
private void ReceiveMessage()
{
statusStripInfo.Invoke(showStatusInfoCallBack, "資料接收中...");
string receiveString = null;
while (true)
{
try
{
IAsyncResult result = receiveMsgDelegate.BeginInvoke(out receiveString, null, null); //異步接收
while (result.IsCompleted == false)
{
Thread.Sleep(50);
if (socket.Connected == false)
return;
}
receiveMsgDelegate.EndInvoke(out receiveString, result);
if (receiveString != null)
{
receiveCount++;
tbxReceiveCount.Invoke(showReceiveCountCallBack, receiveCount.ToString()); //顯示接收計數
lstBoxMsg.Invoke(showMsgCallBack, receiveString);
}
}
catch
{
}
}
}
private void btnSend_Click(object sender, EventArgs e)
{
if (socket!=null && socket.Connected)
{
Thread threadSend = new Thread(new ParameterizedThreadStart(SendMessage));
threadSend.Start(tbxMsg.Text);
}
else
statusStripInfo.Invoke(showStatusInfoCallBack, "socket沒有連接配接!");
}
//發送消息
private void SendMessage(object state)
{
statusStripInfo.Invoke(showStatusInfoCallBack, "正在發送...");
try
{
IAsyncResult result = sendMsgDelegate.BeginInvoke(state.ToString(), null, null); //異步發送
while (result.IsCompleted == false)
{
Thread.Sleep(30);
}
sendMsgDelegate.EndInvoke(result);
statusStripInfo.Invoke(showStatusInfoCallBack, "發送完畢!");
sendCount++;
tbxSendCount.Invoke(showSendCountCallBack, sendCount.ToString()); //顯示發送計數
}
catch
{
statusStripInfo.Invoke(showStatusInfoCallBack, "資料發送時異常,發送失敗!");
}
}
private void btnDisConnect_Click(object sender, EventArgs e)
{
if (socket != null)
{
socket.Close();
}
toolStripStatusInfo.Text = "連接配接斷開!";
btnConnect.Enabled = true;
}
private void btnClear_Click(object sender, EventArgs e)
{
lstBoxMsg.Items.Clear();
sendCount = 0;
receiveCount = 0;
tbxSendCount.Text = sendCount.ToString();
tbxReceiveCount.Text = receiveCount.ToString();
}
}