首页 > 编程语言 >C++socket服务器与客户端简单通信流程

C++socket服务器与客户端简单通信流程

时间:2023-12-07 19:22:31浏览次数:53  
标签:socket 流程 cout C++ flag 服务器 include 客户端

服务器和客户端简单通信的流程,做一个简单的复习:

1.服务器创建的流程


代码如下,各个重要函数已经写注释:

#include <iostream>
// 推荐加上宏定义

#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Windows.h>
#pragma comment(lib, "ws2_32")
using namespace std;
int main()
{
  auto _is_good = [](bool flag, string str)
  {
    if (!flag)
      cout << str << " successfully" << endl;
    else
      cout << str << " failure" << endl;
  };
  char info[] = "hello";
  // 创建 Windows Sockets 2.x版本
  WORD ver = MAKEWORD(2, 2);
  // 初始化 Windows Sockets 库
  // WSAStartup() 函数用于初始化 Windows Sockets 库。
  // ver 参数指定 Windows Sockets 版本号,dat 参数用于接收 Windows Sockets 库的初始化信息。
  WSADATA dat; // Socket的各种数据结构
  WSAStartup(ver, &dat);
  //---------------------------------
  // 1socket API建立简易Tcp服务端
  // 建立一个socket数据类型
  // AF_NET是ipv4,SOCK_STREAM代表流式socket,IPPROTO_TCP代表了TCP协议
  SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  // 2bind绑定用于接受客户端连接的网络端口
  sockaddr_in _sin = {};                  // 表示socket地址,储存端口号和ip
  _sin.sin_family = AF_INET;              // 设置地址族为ipv4
  _sin.sin_port = htons(4567);            // 设置端口号4567,需要htons将主机字节顺序转换成为网络字节顺序
  _sin.sin_addr.S_un.S_addr = INADDR_ANY; // 设置地址为任意地址
  // 将套接字绑定在指定的地址和端口上
  bool flag = (bind(_sock, (sockaddr *)&_sin, sizeof(_sin)) == SOCKET_ERROR);
  _is_good(flag, "bind");
  // 3listen监听网络端口
  // 让套接字进入监听状态,缓冲区最大排队数量为5
  flag = listen(_sock, 5) == SOCKET_ERROR;
  _is_good(flag, "listen");

  sockaddr_in clientAddr = {}; // 创建客户端ip
  int nAddrLen = sizeof(sockaddr_in);
  SOCKET _cSock = INVALID_SOCKET; // 给客户端创建一个套接字,客户端套接字句柄初始化为无效套接字

  while (1)
  {                                                             // 4accept等待接受客户端连接
    _cSock = accept(_sock, (sockaddr *)&clientAddr, &nAddrLen); // 返回值给客户端socket
    flag = (INVALID_SOCKET == _cSock);                          // 判断是否接受到无效客户端socket
    _is_good(flag, "accept");
    cout << "新客户端加入:IP=" << inet_ntoa(clientAddr.sin_addr) << endl;
    // 5send向客户端发送一条数据
    send(_cSock, info, strlen(info) + 1, 0);
    // send函数
    //  ssize_t send(int socket, const void *buf, size_t len, int flags);
    // 参数说明:

    // socket:指定发送端套接字描述符。
    // buf:指向一个存放应用程序要发送数据的缓冲区。
    // len:指定要发送的数据长度。
    // flags:指定发送数据的标志。
    // send函数的返回值:

    // 成功时,返回实际发送的数据长度。
    // 失败时,返回SOCKET_ERROR。
  }
  // 6关闭套接字close socket
  closesocket(_sock);
  //---------------------------------
  // 清理 Windows Sockets 库 WSACleanup() 函数用于清理 Windows Sockets 库。
  WSACleanup();
  return 0;
}

2.客户端创建的流程

#include <iostream>
// 推荐加上宏定义

#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <Windows.h>
#pragma comment(lib, "ws2_32")
using namespace std;
int main()
{
  auto func = [](bool flag, string str)
  {
    if (!flag)
      cout << str << " successfully" << endl;
    else
      cout << str << " failure" << endl;
  };
  char ipaddr[] = "127.0.0.1";
  WORD ver = MAKEWORD(2, 2);
  WSADATA dat;
  WSAStartup(ver, &dat);
  // 创建一个socket
  SOCKET _sock = socket(AF_INET, SOCK_STREAM, 0);
  bool flag = _sock == INVALID_SOCKET;
  func(flag, "socket");
  // 创建连接到服务器端的地址
  sockaddr_in _sin = {};
  _sin.sin_family = AF_INET;
  _sin.sin_port = htons(4567);
  _sin.sin_addr.S_un.S_addr = inet_addr(ipaddr);
  // 连接服务器端
  int ret = connect(_sock, (sockaddr *)&_sin, sizeof(sockaddr_in));
  flag = ret == SOCKET_ERROR;
  func(flag, "connect");
  // 接受服务器消息
  char recvBuf[256] = {};
  int recvLen = recv(_sock, recvBuf, 256, 0);
  /*
recv函数
recv函数用于从TCP连接的另一端接收数据。
recv函数的函数原型如下
C
ssize_t recv(int socket, void *buf, size_t len, int flags);

参数说明:

socket:指定接收端套接字描述符。
buf:指向一个存放应用程序要接收数据的缓冲区。
len:指定要接收的数据长度。
flags:指定接收数据的标志。
recv函数的返回值:

成功时,返回实际接收到的数据长度。
失败时,返回SOCKET_ERROR。
  */
  if (recvLen > 0)
    cout << recvBuf << endl;
  // 关闭socket
  closesocket(_sock);
  WSACleanup();
  return 0;
}

3简单演示:

服务器的启动

双击客户端程序

服务器端接受到相应

多点击几次客户端后服务器端

标签:socket,流程,cout,C++,flag,服务器,include,客户端
From: https://www.cnblogs.com/AndreaDO/p/17883751.html

相关文章

  • C++学习笔记
    目录关键字const枚举switchcase函数常用函数代码块指针智能指针引用类与对象this指针静态成员静态成员变量静态成员函数继承与多态与抽象类动态内存拷贝浅拷贝命名空间I/O文件和流异常处理捕获异常抛出异常模板函数模板类模板STL容器(Containers)vectormap算法(Algorithm)迭代器(Itera......
  • C++(Protocol Buffers)
    ProtocolBuffers(简称Protobuf)是由Google开发的一种轻量级、高效、可扩展的数据序列化协议。它旨在成为一种语言无关、平台无关、可扩展、高效的数据交换格式。Protobuf通常用于在不同的系统或组件之间进行数据通信,如在分布式系统中,或者作为数据存储格式。以下是ProtocolBu......
  • C++(new操作符)
    在C++中,new操作符用于在动态内存(heap)上为对象动态分配内存,同时会调用对象的构造函数进行初始化。它返回一个指向新分配的内存空间的指针。new操作符的一般语法如下:cppCopycodenewtypenewtype[expression]其中,type是要分配内存的数据类型,expression是一个表示要分配......
  • 实验四 Web服务器1-socket编程
    实验四Web服务器1-socket编程基于华为鲲鹏云服务器CentOS中(或Ubuntu),使用LinuxSocket实现:1.time服务器的客户端服务器,提交程序运行截图2.echo服务器的客户端服务器,提交程序运行截图,服务器把客户端传进来的内容加入“服务器进程pid你的学号姓名echo:”返回给客户端3.......
  • 实验四 Web服务器1-socket编程
    time服务器time客户端echo服务器echo客户端......
  • 实验四 Web服务器1-socket编程
    基于华为鲲鹏云服务器CentOS中(或Ubuntu),使用LinuxSocket实现:1.time服务器的客户端服务器,提交程序运行截图3.服务器部署到华为云服务器,客户端用Ubuntu虚拟机。time服务器代码(tms.c)#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include......
  • 实验四 Web服务器1-socket编程
    基于华为鲲鹏云服务器CentOS中(或Ubuntu),使用LinuxSocket实现:1.time服务器的客户端服务器,提交程序运行截图2.echo服务器的客户端服务器,提交程序运行截图,服务器把客户端传进来的内容加入“服务器进程pid你的学号姓名echo:”返回给客户端3.服务器部署到华为云服务器,客户端......
  • C++/CLI 包装引用 Native C++ 简单测试
    托管C++这个项目名:CppCLI。Animals.h#pragmaonceusingnamespaceSystem;namespaceZoological{publicrefclassAnimals{public:intGetLegs();voidSetLegs(intlegs);String^GetName();voidSetName(String^nam......
  • 云课五分钟-05一段代码修改-AI修改C++
    前篇:云课五分钟-04一段代码学习-大模型分析C++在前一节,使用大模型工具文心一言等可以帮助分析代码,加快理解。信息时代→智能时代,系统学习转为碎片学习。发散思维的能力在智能时代尤为重要。 同样我们也可以借助智能化工具修改代码,提出自己的需求。所有的云课五分钟,不仅演示可行案......
  • 阅读《Effective c++》第三版 day 3
    ·考虑提供更搞效且安全的swap函数:对于一般缺省的swap函数,可能引发拷贝构造函数,导致性能下降,swap应设计为提供异常安全性保障而不抛出异常,但缺省版本的swap时可能抛出的,所以重新设计swap是应该的。此前设计operator=函数也有稍微提过。此外考虑类的设计模式,也会有低效率的swap......