服务器端:

#include <winsock.h>
#include<iostream>
#pragma comment(lib,"ws2_32.lib")
#include <Windows.h>
#include <string>DWORD WINAPI ThreadTCP(LPVOID pParam);int main()
{//初始化Windows Socket ApplicationWORD sockVersion = MAKEWORD(2, 2);WSADATA wsaData;//WinSock的注册函数,初始化底层的Windows Sockets DLLif (WSAStartup(sockVersion, &wsaData) != 0)return 0;//创建套接字 SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (slisten == INVALID_SOCKET){std::cout << "create socket error!" << std::endl;return 0;}//绑定IP和端口      sockaddr_in sin;sin.sin_family = AF_INET;//sin.sin_port = htons(8888);//指定端口,将端口号转换为网络字节顺序sin.sin_addr.S_un.S_addr = INADDR_ANY;//bind()把socket绑定到特定的网络地址上if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR){std::cout << "bind error!" << std::endl;return 0;}//开始监听
//启动指定的socket,监听到来的连接请求
5指定了监听socket的等待连接缓冲区队列的最大长度,一般设为5    if (listen(slisten, 5) == SOCKET_ERROR){std::cout << "listen error !" << std::endl;return 0;}//循环接收数据 SOCKET sClient;sockaddr_in remoteAddr;int nAddrlen = sizeof(remoteAddr);while (true){std::cout << "阻塞。。。。等待连接。。。" << std::endl;//接收一个连接请求,并新建一个socket,原来的socket返回监听状态sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen);if (sClient == INVALID_SOCKET){std::cout << "accept error !" << std::endl;continue;}//inet_addr()把一个标准的点分十进制的IP地址转换成长整型的地址数据//inet_ntoa()把长整型的IP地址数据转换成点分十进制的ASCII字符串    std::cout << "接受一个连接:" << inet_ntoa(remoteAddr.sin_addr)<<":"<<remoteAddr.sin_port << std::endl;//创建一个线程与客户端进行会话CreateThread(NULL, 0, ThreadTCP, (LPVOID)sClient, 0, NULL);}closesocket(slisten);//winsock的注销函数,从底层的Windows Sockets DLL 中撤销注册WSACleanup();return 0;
}DWORD WINAPI ThreadTCP(LPVOID pParam)
{SOCKET sClient = (SOCKET)pParam;char revData[255];std::string data = "hello_";int n = 0;while (1){data = "hello_"+std::to_string(n);//接收数据  //从一个已经与对方建立连接的socket接收数据 int ret = recv(sClient, revData, 255, 0);if (ret > 0){revData[ret] = 0x00;std::cout << "第" << n++ << "回:" << revData << std::endl;//printf(revData);}//发送数据    const char * sendData = data.c_str();向一个已经与对方建立连接的socket发送数据   int nb=send(sClient, sendData, strlen(sendData), 0);if (nb != strlen(sendData)){break;}Sleep(5000);}//断开连接std::cout << "断开连接" << std::endl;//关闭socket,释放相应的资源closesocket(sClient);return 0;
}

客户端程序:

#include <winsock.h>
#include<iostream>
#pragma comment(lib,"ws2_32.lib") #include <Windows.h>
#include<string>int main()
{//初始化Windows Socket ApplicationWORD sockVersion = MAKEWORD(2, 2);WSADATA wsaData;//WinSock的注册函数,初始化底层的Windows Sockets DLLif (WSAStartup(sockVersion, &wsaData) != 0)return 0;//创建一个socket并返回socket的标识符SOCKET sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (sclient == INVALID_SOCKET){std::cout << "invalid socket!" << std::endl;return 0;}sockaddr_in serAddr;serAddr.sin_family = AF_INET;serAddr.sin_port = htons(8888);serAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");if (connect(sclient, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR){             //连接失败  std::cout << "connect error !" << std::endl;closesocket(sclient);return 0;}std::string data="abcdef_";int n = 0;while (1){data = "abcdef_"+std::to_string(n);//std::cin >> data;const char * sendData;sendData = data.c_str();//string转const char*         /*      send()用来将数据由指定的socket传给对方主机int send(int s, const void * msg, int len, unsigned int flags)s为已建立好连接的socket,msg指向数据内容,len则为数据长度,参数flags一般设0成功则返回实际传送出去的字符数,失败返回-1,错误原因存于error       */send(sclient, sendData, strlen(sendData), 0);//接收返回的数据char recData[255];int ret = recv(sclient, recData, 255, 0);if (ret > 0){recData[ret] = 0x00;std::cout <<"第"<<n<<"回:"<< recData << std::endl;}if (n++>10){break;}Sleep(500);}//关闭closesocket(sclient);WSACleanup();system("pause");return 0;
}

批注:

数据包1:客户端从端口4671向服务器端口8888发起连接

数据包2:8888应答连接

数据包3:4671应答8888的应答,成功建立连接

客户端程序先send("abcdef_0")【数据包4】,然后阻塞在recv()处等待服务器返回数据,

服务器端程序阻塞在recv,然后接收到客户端程序发送来的"abcdef_0",显示在控制台,

服务器端发送send("hello_0")【数据包6】,然后Sleep(5000)

客户端接收到recv("hello_0"),显示在控制台,然后Sleep(500)

第1个500ms后, 客户端继续发送send("abcdef_1")【数据包8】,然后阻塞在recv()处

服务器端还在Sleep(5000)

直到服务器端Sleep完毕,然后recv("abdef_1"),显示在控制台,并且send("hello_1")【数据包10】,然后Sleep(5000)

客户端从recv("hello_1")处执行,显示在控制台,然后Sleep(500)

客户端Sleep(500)完毕后,又向服务器端发送send("abcdef_2")【数据包12】,然后阻塞在recv()处

服务器端还在Sleep(5000)

直到服务器端Sleep完毕,然后recv("abcdef_2").......重复进行

从分析流程看出,服务器端控制台和客户端控制台显示分别显示"abcdef_xx"   "hello_xx"是基本上同时的

二者的流程控制主要被服务器端的Sleep(5000)拖延,

客户端则相应的在recv()处等待数据

客户端4671发送的最后一个数据"abcdef_11"【数据包48】,之后阻塞5s等待服务器端Sleep完毕返回数据"hello_11"【数据包50】

之后客户端触发了

if (n++>10)
        {
            break;
        }

执行,closesocket(sclient)了,此时,客户端发送了结束会话请求【数据包52】

数据包53:8888应答了4671的结束请求

此后4671还没有继续响应结束请求

在第60s时,8888又向4671发送了数据"hello_12" 【数据包54】,显然该数据客户端不会再recv()了,客户端程序已经完全退出

最后一个数据包55,是4671发送的响应结束会话,之后两个端口间不再通信

问题:

服务器端在第60从Sleep(5000)醒来后,为什么没有阻塞在recv()处,此时并没有收到任何数据,而是向下执行,并且发送了第54个数据包"hello_12"?

C++ TCP 网络编程与数据通信相关推荐

  1. 迈入JavaWeb第一步,Java网络编程基础,TCP网络编程URL网络编程等

    文章目录 网络编程概述 网络通信要素 要素一IP和端口号 要素二网络协议 TCP网络编程 UDP网络编程 URL网络编程 Java网络编程基础 网络编程概述 Java是Internet上的语言,它从语 ...

  2. TCP网络编程的基本流程

    TCP网络编程的基本流程 对于服务端,通常为以下流程: 调用socket函数创建socket 调用bind函数将socket绑定到某个IP和端口上 调用listen开始监听 当有客户端请求连接上来时, ...

  3. 【计算机网络】Linux环境中的TCP网络编程

    文章目录 前言 一.TCP Socket API 1. socket 2. bind 3. listen 4. accept 5. connect 二.封装TCPSocket 三.服务端的实现 1. ...

  4. muduo学习笔记:net部分之实现TCP网络编程库-Buffer

    文章目录 为什么采用non-blocking网络编程中应用层buffer是必需的? Buffer 设计 Buffer::readFd() 线程安全 Muduo Buffer 的数据结构 Muduo B ...

  5. TCP网络编程 [Java]

    TCP网络编程 这里我们通过一个例子来了解什么是TCP网络编程: eg: 问题: -> 从客户端发送文件到服务端,服务端将接受到的客户端发来的文件存储到本地之后并返回一个发送成功给客户端,并关闭 ...

  6. 套接字编程-TCP网络编程

    文章目录 套接字地址结构 通用套接字地址数据结构 以太网协议的套接字地址数据结构 Netlink协议套接字地址结构 TCP网络编程 套接字初始化socket() domain type protoco ...

  7. 粤嵌GEC6818板子TCP网络编程发送命令控制音视频

    TCP网络编程 (1)gec6818网络编程前期准备工作 (1).开发板和Ubuntu系统都处于教室局域网内 1.开发板和电脑(Ubuntu)都需要连接上教室的网线 2.开发板设置ip地址 在开发板终 ...

  8. tcp网络编程客户端和服务端及listen和tcp允许最大连接数

    tcp网络编程 tcp网络编程步骤: 由于tcp传输特点是可靠有连接,那么就有 1.客户端向服务端发送连接请求(SYN), 2.服务端接受请求并向客户端发送(SYN+ACK); 3.客户端向服务端回复 ...

  9. 基于数据库及TCP网络编程实现的电子词典

    目录 一.前言 二.项目介绍 三.功能实现 3.1. 用户注册 3.1.1 功能演示 3.1.2 功能函数实现 3.2. 用户登录 3.2.1 功能演示 3.2.2 功能函数实现 3.3. 查询单词 ...

  10. TCP网络编程----C/S模型 (客户端/服务器模型)的代码实现

    TCP网络编程----C/S模型 (客户端/服务器模型)的代码实现 client发送数据到server,server对数据进行提取并根据用户输入的操作符进行两个数的计算,并将计算结果传给client. ...

最新文章

  1. linux下cd命令
  2. 成功解决Exception “unhandled ModuleNotFoundError“No module named ‘face_recognition.cli‘
  3. 【uoj#94】【集训队互测2015】胡策的统计(集合幂级数)
  4. 网站安全狗”响应内容保护“网页错误返回页面优化功能介绍
  5. C# WebBrowser 设置代理
  6. 以太坊在哪里买_DeFi只是以太坊的开胃小菜,以太坊2.0才是重头戏
  7. 【bfs】Replication G(P7151)
  8. TinyFrame升级之五:全局缓存的设计及实现
  9. Nagios_在不同平台下的安装
  10. php edm 系统,edm.php
  11. 优酷 米兔机器人_ONEBOT积木机器人上手评测,寓教于乐的反履机甲让孩子爱不释手...
  12. Datalogic得利捷推出最新读码产品及终端应用,全面提升企业工业制造生产力
  13. cad计算机绘图知识点,学习Auto CAD制图需要掌握哪些重要的知识点?
  14. 服务器存储扩容技术文档,扩容服务器存储空间
  15. 转帖:在北京5年艰辛快乐的创业经历
  16. 阿里云服务器配置docker及其使用
  17. Django 国际化翻译中的 gettext 和 gettext_lazy
  18. 固态硬盘和机械硬盘的区别是什么
  19. Mapper 与 Reducer 解析
  20. java 新浪短网址生成器_新浪短网址链接生成器 2020最新新浪t.cn短链接在线生成接口推荐...

热门文章

  1. 网站文章采集与伪原创技巧
  2. 计算机组成原理知识点梳理
  3. Hdu 1240 Asteroids题解
  4. 一起学习正则表达式(五)断言匹配
  5. W806做电机转速调控
  6. JAVA算法:三角形周长(JAVA版本算法)
  7. 国产手机厂商抢占高端,二手机市场不容忽视
  8. 详解MPO/MTP主干光纤跳线规格参数、MPO连接说明、MPO极性分类
  9. 论文阅读笔记《Deep Graph Matching under Quadratic Constraint》
  10. 关于视频后期美白的一些事