TCP—传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。
TCP充分实现了数据传输时各种控制功能,可以进行丢包的重发控制,还可以对次序乱掉的分包进行顺序控制。而这些在UDP中都没有。此外,TCP作为一种面向有连接的协议,只有在确认通信对端存在时才会发送数据,从而可以控制通信流量的浪费。TCP通过检验和、序列号、确认应答、重发控制、连接管理以及窗口控制等机制实现可靠性传输。
作者:Aniugel
链接:https://www.jianshu.com/p/e8ea289b478e
来源:简书
其实现方式可以如下所示:
设计界面
设计流程遵循以下原则:
设计步骤代码实现:
1、TCPService
i.套接字的绑定和监听
void CTCPServiceDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
HWND hIpWnd = ::GetDlgItem(this->m_hWnd, IDC_EDIT_IP);
char szIp[MAX_PATH] = { 0 };
::GetWindowText(hIpWnd, szIp, MAX_PATH);
HWND hPortWnd = ::GetDlgItem(this->m_hWnd, IDC_EDIT_PORT);
char szPort[MAX_PATH] = { 0 };
::GetWindowText(hPortWnd, szPort, MAX_PATH);
if(SocketBindListen(szIp, atoi(szPort)))
{
AddText("Listen……", "[Listen]");
}
}
BOOL CTCPServiceDlg::SocketBindListen(char *lpszIp, int iPort)
{
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET == sock)
{
return FALSE;
}
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(iPort);
addr.sin_addr.S_un.S_addr = inet_addr(lpszIp);
if(0 != bind(sock, (sockaddr *)(&addr), sizeof(addr)))
{
return FALSE;
}
if(0 != listen(sock, 1))
{
return FALSE;
}
m_sock = sock;
::CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ThreadProc, this, NULL, NULL);// 多线程
return TRUE;
}
ii.发送信息
void CTCPServiceDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
HWND hWnd = ::GetDlgItem(this->m_hWnd, IDC_EDIT_SEND);
char szSend[MAX_PATH] = { 0 };
::GetWindowText(hWnd, szSend, MAX_PATH);
send(m_clientsock, szSend, (1 + ::lstrlen(szSend)), 0);
}
iii.多线程接受信息
UINT CTCPServiceDlg::ThreadProc(LPVOID lpVoid)
{
CTCPServiceDlg *lpThis = (CTCPServiceDlg *)lpVoid;
lpThis->AcceptRecv();
return 0;
}
void CTCPServiceDlg::AcceptRecv()
{
sockaddr_in addr = { 0 };
int iLen = sizeof(addr);
SOCKET sock = accept(m_sock, (sockaddr *)(&addr), &iLen);
m_clientsock = sock;
char szBuf[MAX_PATH] = { 0 };
while (TRUE)
{
int iRet = recv(sock, szBuf, MAX_PATH, 0);
if (0>=iRet)
{
continue;
}
AddText(szBuf, "[recv]");
}
}