zoukankan      html  css  js  c++  java
  • TCP数据流

    服务器端:Server

    #include <iostream>
    using namespace std;
    #define WIN32_LEAN_AND_MEAN
    
    //#include <windows.h>其中包含winsock.h,与winsock2.h重定义
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <stdio.h>
    
    #pragma comment(lib, "ws2_32.lib")
    
    int main()
    {
        //1.加载库
        WORD wVersionRequested;
        WSADATA wsaData;
        wVersionRequested = MAKEWORD(2, 2);
    
        int err = WSAStartup(wVersionRequested, &wsaData);
        if (err != 0) {
            printf("WSAStartup failed with error: %d
    ", err);
            return 1;
        }
    
        if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
            printf("Could not find a usable version of Winsock.dll
    ");
            WSACleanup();
            return 1;
        }
        else
            printf("The Winsock 2.2 dll was found okay
    ");
        //2.Socket 
        SOCKET socklisten = socket(AF_INET ,SOCK_STREAM ,IPPROTO_TCP );
        if(socklisten == INVALID_SOCKET)
        {
            WSACleanup();
            return 1;
        }
        //3.bind
        SOCKADDR_IN addr;
        addr.sin_family = AF_INET;
        addr.sin_addr.S_un.S_addr = inet_addr("192.168.3.154");//INADDR_ANY任意IP
        addr.sin_port = htons(1234);
        if(SOCKET_ERROR == bind(socklisten,(sockaddr*)&addr , sizeof(addr)))
        {
            closesocket(socklisten);
    WSACleanup();
    return 1; } //4.listen if(SOCKET_ERROR == listen(socklisten ,10)) { closesocket(socklisten); WSACleanup(); return 1; } //5.accept SOCKET sockWaiter = accept(socklisten,0,0); if(INVALID_SOCKET == sockWaiter) { closesocket(socklisten); WSACleanup(); return 1; } //6.recv,send char str[1024] = {0}; int nlen; while(1) { nlen = recv(sockWaiter,str,sizeof(str),0); if(nlen > 0) { cout<<str<<endl; cin>>str; send(sockWaiter ,str,sizeof(str),0); } } //7. closesocket(sockWaiter); closesocket(socklisten); //8. WSACleanup(); system("pause"); return 0; }

    客户端:Client#include <iostream>

    using namespace std;
    #define WIN32_LEAN_AND_MEAN
    
    //#include <windows.h>其中包含winsock.h,与winsock2.h重定义
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <stdio.h>
    
    #pragma comment(lib, "ws2_32.lib")
    
    int main()
    {
    
        WORD wVersionRequested;
        WSADATA wsaData;
        wVersionRequested = MAKEWORD(2, 2);
    
        int err = WSAStartup(wVersionRequested, &wsaData);
        if (err != 0) {
            printf("WSAStartup failed with error: %d
    ", err);
            return 1;
        }
        if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
            printf("Could not find a usable version of Winsock.dll
    ");
            WSACleanup();
            return 1;
        }
        else
            printf("The Winsock 2.2 dll was found okay
    ");
        //2.Socket 
        SOCKET sockConnect = socket(AF_INET ,SOCK_STREAM ,IPPROTO_TCP );
        if(sockConnect == INVALID_SOCKET)
        {
            WSACleanup();
            return 1;
        }
        //3.Connect
        SOCKADDR_IN addr;
        addr.sin_family = AF_INET;
        addr.sin_addr.S_un.S_addr = inet_addr("192.168.3.154");
        addr.sin_port = htons(1234);
        if(SOCKET_ERROR == connect(sockConnect,(sockaddr*)&addr , sizeof(addr)))
        {
            closesocket(sockConnect);
            WSACleanup();
            return 1;
        }
        //4.recv,send
        char str[1024] = {0};
        int nlen;
        while(1)
        {
            cin>>str;
            nlen = send(sockConnect ,str,sizeof(str),0);
            if(nlen > 0)
            {
                nlen = recv(sockConnect,str,sizeof(str),0);
                if(nlen > 0)
                    cout<<str<<endl;
            }
        }
        //5.关闭套接字
        closesocket(sockConnect);
        //6.关闭库
        WSACleanup();
        system("pause");
    return 0; }

    一个服务器端怎样连接多个客户端?多线程。

    服务器端的接收缓冲区小于客户端的发送缓冲区:数据流可任意拆分 缺点:出现粘包现象(发送过快,网络中卡住)

    解决方法:长连接和短连接(各自建立socket)

            设置包头,发送数据长度

    SYN:请求连接

    ASK:回复

    PSH:推送数据

    RST:重置连接

    URG:紧急指针

    FIN:断开连接

    TCP的三次握手

    SYN置1就表示这是一个连接请求或连接接受报文。

    规定SYN=1时不能携带数据,但要消耗一个序号

    规定连接建立后所有发送的报文的ACK必须为1

    为什么要三次握手?(两次确认)

    TCP为全双工通信,要互相确认连接才可以传送数据。举一个例子,A发送了两次SYN连接请求,第一次发送的滞留在网络中,第二次发送的与B建立了连接,结束后断开了连接,这时,滞留在网络中的第一次发送的SYN连接请求到达了B,B回复了SYN和ACK,要是两次握手的情况下(即没有A的确认就确认了连接)这是B等待A发送数据,A没有发送过连接请求所以不会理会B。浪费了B的资源。

     四次挥手

    为什么要有2MSL?

    1.允许老的重复分节在网络中消失

    2.保证正常结束

    A发送的ACK没有发送到B,B超时重传一个FIN,A可以重新发送ACK,

    为什么3次握手要4次挥手?

    因为在连接时,Server收到SYN后返回的ASK和SYN一起发送。但是在断开连接时,收到FIN报文后不能立即关闭socket,所以先回复ASK.当Server端都报文发送完毕后仔发送FIN报文。所以需要4次挥手。

  • 相关阅读:
    UIScrollerView遇到UINavigationController
    iOS 自动化打包
    最最基本的SQL常用命令
    导入样式表与外部样式表的区别
    jdk、jre、JVM的简单区别与联系
    JDBC驱动的四种类型
    将映射中的值进行排序并输出键
    Java优先级队列
    Java线程池
    Callable--创建有返回值的线程
  • 原文地址:https://www.cnblogs.com/Lune-Qiu/p/8536078.html
Copyright © 2011-2022 走看看