基于windowns下的TCP网络通信编程

Tcp通信的三次握手和四次挥手

TCP的三次握手和四次挥手是TCP连接的建立和断开过程,确保了可靠的数据传输和连接状态的正确管理。

TCP的三次握手(TCP 链接建立):
1. 客户端发送 SYN 客户端向服务器发送一个 SYN 报文段( SYN=1 Seq=x ),表示请求建立连接。
2. 服务器发送 SYN+ACK 服务器收到 SYN 报文段后,如果同意建立连接,则会发送一个 SYN+ACK 报文段( SYN=1 ACK=x+1 Seq=y ),表示确认客户端的请求,并表示自己也想建立连接。
3. 客户端发送 ACK 客户端收到服务器的 SYN+ACK 报文段后,会发送一个确认报文段( ACK=1 ACK=y+1 Seq=x+1 ),表示确认收到服务器的确认,连接建立成功。
TCP的四次挥手(TCP 链接断开):
1. 客户端发送 FIN 客户端请求断开连接,发送一个 FIN 报文段( FIN=1 Seq=x )。
2. 服务器发送 ACK 服务器收到客户端的 FIN 报文段后,会发送一个确认报文段( ACK=1 ACK=x+1 Seq=y ),表示收到了客户端的请求,但是还有数据需要发送。
3. 服务器发送 FIN 服务器发送完所有数据后,会发送一个 FIN 报文段( FIN=1 ACK=x+1 Seq=y ),表示自己也准备断开连接。
4. 客户端发送 ACK 客户端收到服务器的 FIN 报文段后,会发送一个确认报文段( ACK=1 ACK=y+1 Seq=x+1 ),表示确认收到服务器的请求,连接断开。

通过三次握手,客户端和服务器之间建立了可靠的双向连接。而通过四次挥手,双方断开了连接,确保数据传输的可靠性和正确性。

客户端:

1. 初始化Winsock库: 在使用任何套接字编程功能之前,需要初始化 Winsock 库。可以使用 WSAStartup 函数来完成初始化。
2. 创建套接字: 使用 socket 函数创建一个套接字。指定地址族为 AF_INET,类型为 SOCK_STREAM,协议为 IPPROTO_TCP。
3. 设置服务器地址和端口: 创建一个 sockaddr_in 结构体,并设置其中的地址族、IP地址和端口号,用于连接服务器。
4. 连接服务器: 使用 connect 函数连接到服务器。将创建的套接字和服务器地址作为参数传递给 connect 函数。
5. 发送和接收数据: 使用 send 函数向服务器发送数据,并使用 recv 函数接收服务器的响应数据。
6. 关闭套接字: 使用 closesocket 函数关闭套接字。
7. 清理Winsock库: 在程序退出前,使用 WSACleanup 函数清理 Winsock 库的资源。
#include <iostream>
#include <string>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")

int main() {
    // 初始化Winsock
    WSADATA wsData;
    WORD ver = MAKEWORD(2, 2);
    int wsOK = WSAStartup(ver, &wsData);
    if (wsOK != 0) {
        std::cerr << "Error: Can't initialize Winsock! Quitting" << std::endl;
        return 1;
    }

    // 创建socket
    SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (clientSocket == INVALID_SOCKET) {
        std::cerr << "Error: Can't create socket! Quitting" << std::endl;
        WSACleanup();
        return 1;
    }

    // 连接到服务器
    sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(54000);
    inet_pton(AF_INET, "127.0.0.1", &server.sin_addr);

    if (connect(clientSocket, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) {
        std::cerr << "Error: Can't connect to server! Quitting" << std::endl;
        closesocket(clientSocket);
        WSACleanup();
        return 1;
    }

    // 发送和接收数据
    char buffer[4096];
    std::string userInput;
    do {
        std::cout << "Enter a message: ";

        std::getline(std::cin, userInput);

        int sendResult = send(clientSocket, userInput.c_str(), userInput.size() + 1, 0);
        if (sendResult != SOCKET_ERROR) {
            // 接收服务器回复
            memset(buffer, 0, sizeof(buffer)); // 清空缓冲区
            int bytesReceived = recv(clientSocket, buffer, sizeof(buffer), 0);
            if (bytesReceived > 0) {
                std::cout << "Server response: " << std::string(buffer, bytesReceived) << std::endl;
            }
        }
        else {
            std::cerr << "Error: Send failed! Quitting" << std::endl;
            break;
        }
    } while (userInput != "quit");

    // 关闭客户端socket
    closesocket(clientSocket);

    // 关闭Winsock
    WSACleanup();

    return 0;
}

服务端:

在Windows平台上创建TCP服务器的基本步骤:

1. 初始化Winsock库: 在使用任何套接字编程功能之前,需要初始化 Winsock 库。可以使用 WSAStartup 函数来完成初始化。
2. 创建套接字: 使用 socket 函数创建一个套接字。指定地址族为 AF_INET ,类型为 SOCK_STREAM ,协议为 IPPROTO_TCP
3. 设置服务器地址和端口: 创建一个 sockaddr_in 结构体,并设置其中的地址族、IP地址和端口号,用于绑定服务器的地址和端口。
4. 绑定地址和端口: 使用 bind 函数将套接字绑定到指定的地址和端口上。
5. 监听连接请求: 使用 listen 函数开始监听来自客户端的连接请求。
6. 接受连接: 使用 accept 函数接受客户端的连接请求,并创建一个新的套接字用于与客户端通信。在接受连接之前,服务器会阻塞在这一步,直到有客户端连接上来。
7. 接收和发送数据: 使用新创建的套接字进行数据的接收和发送。可以使用 recv 函数接收来自客户端的数据,使用 send 函数发送数据给客户端。
8. 关闭连接: 当通信完成后,使用 closesocket 函数关闭与客户端的连接。
9. 关闭服务器套接字: 当服务器不再接受新的连接时,使用 closesocket 函数关闭服务器套接字。
#include <iostream>
#include <string>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")

int main() {
    // 初始化Winsock
    WSADATA wsData;
    WORD ver = MAKEWORD(2, 2);
    int wsOK = WSAStartup(ver, &wsData);
    if (wsOK != 0) {
        std::cerr << "Error: Can't initialize Winsock! Quitting" << std::endl;
        return 1;
    }

    // 创建socket
    SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSocket == INVALID_SOCKET) {
        std::cerr << "Error: Can't create socket! Quitting" << std::endl;
        WSACleanup();
        return 1;
    }

    // 绑定地址和端口
    sockaddr_in hint;
    hint.sin_family = AF_INET;
    hint.sin_port = htons(54000);
    hint.sin_addr.S_un.S_addr = INADDR_ANY; // 监听所有网卡上的连接
    bind(serverSocket, (sockaddr*)&hint, sizeof(hint));

    // 开始监听
    listen(serverSocket, SOMAXCONN);

    // 接受连接
    sockaddr_in client;
    int clientSize = sizeof(client);
    SOCKET clientSocket = accept(serverSocket, (sockaddr*)&client, &clientSize);

    // 关闭服务器socket
    closesocket(serverSocket);

    // 接收和发送数据
    char buffer[4096];
    while (true) {
        memset(buffer, 0, sizeof(buffer)); // 清空缓冲区
        int bytesReceived = recv(clientSocket, buffer, sizeof(buffer), 0);
        if (bytesReceived == SOCKET_ERROR) {
            std::cerr << "Error in recv(). Quitting" << std::endl;
            break;
        }

        if (bytesReceived == 0) {
            std::cout << "Client disconnected" << std::endl;
            break;
        }

        std::cout << "Received: " << std::string(buffer, 0, bytesReceived) << std::endl;

        // Echo回消息给客户端
        send(clientSocket, buffer, bytesReceived, 0);
    }

    // 关闭客户端socket
    closesocket(clientSocket);

    // 关闭Winsock
    WSACleanup();

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/556901.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微纤维眼镜清洁布的革命性进化

在日常生活中&#xff0c;眼镜是许多人不可或缺的日常用品&#xff0c;无论是视力矫正还是防护眼睛免受阳光的伤害。然而&#xff0c;眼镜的清洁常常是一个令人头疼的问题&#xff0c;特别是在面对指纹、灰尘和其他污垢时。传统的清洁方法往往需要化学清洁剂&#xff0c;不仅繁…

【css】select实现placeholder效果

场景&#xff1a;使用select下拉选择框的时候&#xff0c;需要像其他控件一样提示默认信息。 问题&#xff1a;表单控件select没有placeholder属性。 解决方案&#xff1a;通过css实现&#xff0c;不需要js <style>select > option[disabled]{ color:#999;cursor: n…

如何用Python构建一个生产级别的电影推荐系统 - 机器学习手册

构建项目是彻底学习概念并发展必要技能的最有效方式之一。 项目使您沉浸在现实世界的问题解决中&#xff0c;巩固您的知识&#xff0c;并培养批判性思维、适应能力和项目管理专业知识。 本指南将带您逐步构建一个根据用户喜好量身定制的电影推荐系统。我们将利用一个庞大的包…

Homebrew安装与卸载

卸载 /bin/bash -c "$(curl -fsSL https://gitee.com/ineo6/homebrew-install/raw/master/uninstall.sh)"安装 /bin/bash -c "$(curl -fsSL https://gitee.com/ineo6/homebrew-install/raw/master/install.sh)"1、复制命令到命令行执行&#xff0c;输入1…

多模态中的视觉编码器clip以及输入分辨率

在多模态的视觉编码主干中&#xff0c;若采用分类的backbone效果很差&#xff0c;经过语义对齐的backbone&#xff0c;比如clip的vit&#xff0c;效果则好很多。 1.Cogvlm中的EVA2-CLIP-E&#xff0c;VIT中最后一层被移除&#xff0c;4.4B&#xff0c;支持分辨率为334/490. 2.…

[源码分享]基于Unity的Live2D虚拟人物——结合了GPT、Azure、情绪识别和口型同步,也可以集合苹果Vision Pro做成3D的形象

# 技术文档 ## 1 项目简介 ### 项目目录 ``` Assets ├─ Animator // 动画 ├─ Code // 代码 │ ├─ AI // AI 模块 │ │ ├─ LM // 语言模型模块 │…

Python爬虫数据可视化分析

Python爬虫用于从网络上获取数据&#xff0c;数据可视化分析则是将获取的数据进行可视化展示和分析&#xff0c;帮助我们更好地理解数据、发现规律、做出决策。下面是一个基本的Python爬虫数据可视化分析的流程&#xff1a; 步骤一&#xff1a;数据爬取 1.选择合适的爬虫工具&a…

使用PL\SQL将Excel表格导入到oracle数据库中

因为要测试生产问题&#xff0c;需要把生产上oracle导出数据导入到测试环境oracle数据库中&#xff0c;尝试了N种方法&#xff0c;发现使用PL\SQL 的ODBC 方法比较好用 1、开始 首先使用plsqldev里面的&#xff0c;工具--》下面的odbc导入器 2、配置 点击之后&#xff0c;会…

LUA脚本判断是否为空

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 Lua是一个小巧的脚…

MOS产品在储能上的应用分析与推荐

电化学储能可与光伏、风电等新能源发电相结合&#xff0c;缓解可再生能源稳定性差的问题。同时&#xff0c;电化学储能可提供调峰、调频、AGC、黑启动等辅助服务&#xff0c;保障电网安全。此外&#xff0c;电化学储能可以起到削峰填谷的作用&#xff0c;为住宅、工业和商业用户…

阻塞队列(模拟+生产者消费者)

阻塞队列 字面意思&#xff0c;带有阻塞功能的队列&#xff0c;满足队列先进先出的性质 作用&#xff1a; 1.如果队列为空&#xff0c;此时执行出队列操作&#xff0c;就会阻塞&#xff0c;直到往此队列里添加元素为止&#xff08;队列不为空&#xff09; 2.如果队列为满&#…

GIS地理信息平台+智慧巡检技术解决方案(Word原件)

1.系统概述 1.1.需求描述 1.2.需求分析 1.3.重难点分析 1.4.重难点解决措施 2.系统架构设计 2.1.系统架构图 2.2.关键技术 3.系统功能设计 3.1.功能清单列表软件全套精华资料包清单部分文件列表&#xff1a; 工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项…

故障诊断 | 基于迁移学习和SqueezeNet 的滚动轴承故障诊断(Matlab)

目录 效果一览基本介绍程序设计参考文献 效果一览 基本介绍 将一维轴承振动信号转换为二维尺度图&#xff08;时频谱图&#xff09;&#xff0c;并使用预训练网络应用迁移学习对轴承故障进行分类。 迁移学习显著减少了传统轴承诊断方法特征提取和特征选择所花费的时间&#xff…

果园系统养殖游戏喂养偷菜种植浇水养成小程序功能介绍

以下是上述功能介绍的重写版本&#xff1a; 装扮 使用丰富的材料&#xff0c;为您的房屋增添独特魅力&#xff0c;展现个性化装饰风格。 土地升级 投入不同数量的材料&#xff0c;提升房屋与土地的品质&#xff0c;打造独一无二的庄园。 日志 通过日志记录&#xff0c;清…

[Leetcode]用栈实现队列

用栈实现队列&#xff1a; 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、pop、peek、empty&#xff09;&#xff1a; 实现 MyQueue 类&#xff1a; void push(int x) 将元素 x 推到队列的末尾int pop() 从队列的开头移除并返回元…

SQL优化——访问路径(ACCESS PATH)

文章目录 1、常见访问路径1.1、TABLE ACCESS FULL1.2、TABLE ACCESS BY USER ROWID1.3、TABLE ACCESS BY ROWID RANGE1.4、TABLE ACCESS BY INDEX ROWID1.5、INDEX UNIQUE SCAN1.6、INDEX RANGE SCAN1.7、INDEX SKIP SCAN1.8、INDEX FULL SCAN1.9、INDEX FAST FULL SCAN1.10、I…

AI的十大趋势如何?斯坦福《2024年人工智能指数报告》告诉你

最近&#xff0c;全球著名华人人工智能学者李飞飞联合领导的斯坦福大学以人为本人工智能研究所&#xff08;Stanford HAI&#xff09;发布了《2024 年人工智能指数报告》&#xff08;Artificial Intelligence Index Report 2024&#xff09;。 《2024 年人工智能指数报告》下载…

windows terminal屏幕分栏的打开和关闭快捷键

最近看的工程基于windows的&#xff0c;自学c语法基于vm里的Ubuntu&#xff0c;win的终端好难用&#xff0c;搞得我好分裂。win系统找到了一个还不错的终端程序&#xff0c;总是记不住常用的快捷键&#xff0c;就记录下。 &#xff08;安装也超简单&#xff0c;直接在MicroSoft…

Vmware 虚拟机自定义IP地址 - UbuntuServer2204

Vmware 虚拟机自定义IP地址 - UbuntuServer2204 设置网段 选择喜欢的网段&#xff0c; 例如&#xff1a; 166 自定义 IP地址 打开虚拟机&#xff0c; 输入命令查看网卡名 ip addr查看网卡配置文件 ls -al /etc/netplan/编辑网卡配置文件 sudo vim /etc/netplan/00-installe…

linux 的Jdk1.8详细安装部署教程

一、环境准备 1.下载安装包 下载地址&#xff0c;这是1.8的你也可以选择安装别的版本的 https://www.oracle.com/java/technologies/downloads/#java8-windows 选择想要的系统和对应的位数&#xff0c;点击下载即可 2.上传安装包 选择自己要安装的路径&#xff0c;&#x…
最新文章