socket TCP 通信

socket TCP 通信

SOCKET可用于主机间或者进程间通信等。
TCP/UDP通信流程:
这里写图片描述
代码(本机TCP):
Server:

//启动监听线程
void CSocketDlg::OnBnClickedStart()
{
    m_run = TRUE;
    if (!AfxBeginThread(CSocketDlg::StartRecvThread, this, THREAD_PRIORITY_ABOVE_NORMAL))
    {
        OutputDebugString("func:AfxBeginThread StartRecvThread failed");
        return;
    }
}
//停止监听线程
void CSocketDlg::OnBnClickedStop()
{
    m_run = FALSE;
    SOCKADDR_IN addr;
    addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8101);
    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);//因为accept阻塞的,这样能够正常退出监听线程
    CString msg;
    connect(sock, (SOCKADDR*)&addr, sizeof(SOCKADDR));
    closesocket(sock);
}
//监听线程
UINT CSocketDlg::StartRecvThread(LPVOID para)
{
    //创建套接字
    WORD myVersionRequest;
    WSADATA wsaData;
    myVersionRequest = MAKEWORD(2, 2);
    int err;
    err = WSAStartup(myVersionRequest, &wsaData);
    if (err != 0)
    {
        CString s;
        s.Format(_T("func:WSAStartup failed,error:%d"), GetLastError());
        OutputDebugString(s);
        char cstrNewDosCmd[] = "netsh.exe winsock reset";
        STARTUPINFO si;
        ZeroMemory(&si, sizeof(STARTUPINFO));
        si.cb = sizeof(STARTUPINFO);
        GetStartupInfo(&si);
        si.wShowWindow = SW_HIDE;
        si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
        PROCESS_INFORMATION pi;
        // 启动进程  
        DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT | CREATE_NO_WINDOW;
        BOOL bSuc = CreateProcess(NULL, cstrNewDosCmd, NULL, NULL, TRUE, dwCreationFlag, NULL, NULL, &si, &pi);
        WaitForSingleObject(pi.hProcess, 5000);
        err = WSAStartup(myVersionRequest, &wsaData);
        if (err != 0)
            return 0;
    }
    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
    {
        CString s;
        s.Format(_T("func:WSAStartup version not ok,error:%d"), GetLastError());
        OutputDebugString(s);
        WSACleanup();
        return 0;
    }

    SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, 0);//创建了可识别套接字
    SOCKADDR_IN listenAddr;
    listenAddr.sin_family = AF_INET;
    listenAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//ip地址
    listenAddr.sin_port = htons(8101);//绑定端口
    int flag = 1;
    int len = sizeof(int);
    if (setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&flag, len) == -1)
    {
        CString s;
        s.Format(_T("set reuse recvSock IP:%s port:%d failed ,error:%d"), inet_ntoa(listenAddr.sin_addr), listenAddr.sin_port, WSAGetLastError());
        OutputDebugString(s);
    }
    if (SOCKET_ERROR == bind(listenSocket, (SOCKADDR*)&listenAddr, sizeof(SOCKADDR)))
    {
        CString s;
        s.Format(_T("bind recvSock IP:%s port:%d failed ,error:%d"), inet_ntoa(listenAddr.sin_addr), listenAddr.sin_port, WSAGetLastError());
        OutputDebugString(s);
        closesocket(listenSocket);
        WSACleanup();
        return 0;
    }
    if (SOCKET_ERROR == listen(listenSocket, 5))
    {
        CString s;
        s.Format(_T("listen recvSock IP:%s port:%d failed ,error:%d"), inet_ntoa(listenAddr.sin_addr), listenAddr.sin_port, WSAGetLastError());
        OutputDebugString(s);
        closesocket(listenSocket);
        WSACleanup();
        return 0;
    }
    OutputDebugString("StartRecvThread OK");
    CSocketDlg * pParent = (CSocketDlg *)para;
    SOCKADDR_IN clientsocket;
    int AddrLen = sizeof(SOCKADDR);
    TCHAR recvBuf[4096];
    while (pParent->m_run)
    {
        ZeroMemory(recvBuf, 4096);
        SOCKET serConn = accept(listenSocket, (SOCKADDR*)&clientsocket, &AddrLen);
        if (serConn == INVALID_SOCKET)
        {
            CString msg;
            msg.Format("server sccept error:%d", WSAGetLastError());
            OutputDebugString(msg);
            continue;
        }
        OutputDebugString("server StartRecvThread accept");
        int recvLen = recv(serConn, recvBuf, 4096, 0);
        OutputDebugString(recvBuf);
        if (recvLen < 1)
        {
            CString msg;
            msg.Format("server recv error:%d", WSAGetLastError());
            OutputDebugString(msg);
            closesocket(serConn);//关闭
            continue;
        }
        CString sendText;
        pParent->m_editSend.GetWindowText(sendText);
        SOCKADDR_IN sendAddr;
        sendAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
        sendAddr.sin_family = AF_INET;
        sendAddr.sin_port = htons(8102);
        if (SOCKET_ERROR != send(serConn, sendText, sendText.GetLength(), 0))
        {
            OutputDebugString("server send ok");
        }
        else
        {
            OutputDebugString("server send error");
        }
        CString text;
        pParent->m_edit.GetWindowText(text);
        text = text+ "接收到:"+CString(recvBuf)+"\r\n"+"发送:"+sendText+"\r\n";
        pParent->m_edit.SetWindowText(text);
        pParent->m_edit.LineScroll(pParent->m_edit.GetLineCount() - 1, 0);
        closesocket(serConn);//关闭
    }
    closesocket(listenSocket);
    WSACleanup();
    OutputDebugString("StartRecvThread STOP");
    return 0;
}

Client:

void CSocketClientDlg::OnBnClickedSend()
{//创建套接字
    WORD myVersionRequest;
    WSADATA wsaData;
    myVersionRequest = MAKEWORD(2, 2);
    int err;
    err = WSAStartup(myVersionRequest, &wsaData);
    if (err != 0)
    {
        CString s;
        s.Format(_T("func:WSAStartup failed,error:%d"), GetLastError());
        OutputDebugString(s);
        char cstrNewDosCmd[] = "netsh.exe winsock reset";
        STARTUPINFO si;
        ZeroMemory(&si, sizeof(STARTUPINFO));
        si.cb = sizeof(STARTUPINFO);
        GetStartupInfo(&si);
        si.wShowWindow = SW_HIDE;
        si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
        PROCESS_INFORMATION pi;
        // 启动进程  
        DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT | CREATE_NO_WINDOW;
        BOOL bSuc = CreateProcess(NULL, cstrNewDosCmd, NULL, NULL, TRUE, dwCreationFlag, NULL, NULL, &si, &pi);
        WaitForSingleObject(pi.hProcess, 5000);
        err = WSAStartup(myVersionRequest, &wsaData);
        if (err != 0)
            return;
    }
    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
    {
        CString s;
        s.Format(_T("func:WSAStartup version not ok,error:%d"), GetLastError());
        OutputDebugString(s);
        WSACleanup();
        return;
    }
    OutputDebugString("CSocketClientDlg StartSendThread OK");
    SOCKADDR_IN sendAddr;
    sendAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    sendAddr.sin_family = AF_INET;
    sendAddr.sin_port = htons(8101);
    CString sendText;
    m_editSend.GetWindowText(sendText);
    SOCKET SendSocket = socket(AF_INET, SOCK_STREAM, 0);//创建了可识别套接字
    CString msg;
    if (SOCKET_ERROR != connect(SendSocket, (SOCKADDR*)&sendAddr, sizeof(SOCKADDR)))
    {
        if (SOCKET_ERROR != send(SendSocket, sendText.GetBuffer(), sendText.GetLength(), 0))
        {
            OutputDebugString("CSocketClientDlg client send ok");
            char recvBuf[4096] = { 0 };
            if (recv(SendSocket, recvBuf, 4096, 0) > 0)
            {
                CString recvText;
                m_editRecv.GetWindowText(recvText);
                recvText = recvText + "client recv: " + CString(recvBuf) + "\r\n";
                m_editRecv.SetWindowText(recvText);
                m_editRecv.LineScroll(m_editRecv.GetLineCount()-1, 0);//CEdit自动滚动
            }
            else
            {
                msg.Format("CSocketClientDlg recv error:%d", WSAGetLastError());
                OutputDebugString(msg);
            }
        }
        else
        {
            msg.Format("CSocketClientDlg StartSendThread send error:%d", WSAGetLastError());
            OutputDebugString(msg);
        }
    }
    else
    {
        msg.Format("CSocketClientDlg connect error:%d", WSAGetLastError());
        OutputDebugString(msg);
    }
    closesocket(SendSocket);
    WSACleanup();
    return;
}

几个点:

m_editRecv.LineScroll(m_editRecv.GetLineCount()-1, 0);//CEdit自动滚动到最后一行
m_editSend.ShowScrollBar(SB_VERT, TRUE);//CEdit加上垂直滚动条
//accept阻塞,可以链接一下让它退出
SOCKADDR_IN addr;
addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
addr.sin_family = AF_INET;
addr.sin_port = htons(8101);
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
CString msg;
connect(sock, (SOCKADDR*)&addr, sizeof(SOCKADDR));
closesocket(sock);
//有时候WSAStartup失败,可以重试下,或者执行下netsh winsock reset
CString s;
s.Format(_T("func:WSAStartup failed,error:%d"), GetLastError());
OutputDebugString(s);
char cstrNewDosCmd[] = "netsh.exe winsock reset";
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.wShowWindow = SW_HIDE;
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
PROCESS_INFORMATION pi;
DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT | CREATE_NO_WINDOW;
BOOL bSuc = CreateProcess(NULL, cstrNewDosCmd, NULL, NULL, TRUE, dwCreationFlag, NULL, NULL, &si, &pi);// 启动进程  
WaitForSingleObject(pi.hProcess, 5000);

效果:
这里写图片描述
代码链接:
VS2015工程:http://download.csdn.net/detail/yangyang031213/9893802
https://github.com/yangyang0312/cpp/tree/master/windows/Socket

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HTML 是一种标记语言,它主要用于描述网页的结构和内容,而 SocketTCP 则是两种通信协议。HTML 本身并不直接提供 SocketTCP 通信的功能,但是可以通过 JavaScript 等脚本语言来实现相关的功能。 以下是一个使用 JavaScript 实现 Socket TCP 通信的简单代码示例: ``` <!DOCTYPE html> <html> <head> <title>Socket TCP Communication</title> </head> <body> <h1>Socket TCP Communication</h1> <textarea id="log" rows="10" cols="50"></textarea><br><br> <input type="text" id="message"><br><br> <button onclick="send()">Send</button> <script> var socket = new WebSocket("ws://localhost:8080"); socket.onopen = function() { log("Connected to server."); }; socket.onmessage = function(event) { log("Received message from server: " + event.data); }; function send() { var message = document.getElementById("message").value; socket.send(message); log("Sent message to server: " + message); } function log(message) { var log = document.getElementById("log"); log.value += message + "\n"; } </script> </body> </html> ``` 这个页面包含了一个文本框、一个按钮和一个日志窗口。当用户点击按钮时,页面会使用 WebSocket 对象连接到本地的服务器(地址为 ws://localhost:8080),并发送文本框中的内容。当服务器接收到消息后,会将消息发送回页面,页面会将收到的消息显示在日志窗口中。在 JavaScript 中,我们可以使用 WebSocket 对象来处理 Socket TCP 通信。在这个例子中,我们使用了 WebSocket 对象的 `onopen`、`onmessage` 和 `send` 方法来处理连接、接收消息和发送消息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值