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();
}
}