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次挥手。

原文地址:https://www.cnblogs.com/Lune-Qiu/p/8536078.html