当前位置: 首页 > news >正文

C++s简单实现Scoket编程

只实现了服务器端的服务
和其他语言一样,实现通信需要以下步骤

  1. 创建socket套接字
  2. 定义服务端地址和端口
  3. 服务端绑定地址和端口
  4. 服务端进行端口监听
  5. 服务端与客户端进行连接
  6. 服务端接收客户端发送的信息
  7. 服务端返回信息给客户端
  8. 关闭套接字

首先要导入socket库

文章目录

  • 1. 导入winsock.h库函数
  • 2. 创建套接字
  • 3. 定义服务端地址和端口
  • 4. 绑定端口和地址
  • 5. 开始监听
  • 6. 创建接收套接字地址
  • 7.接收套接字建立连接
  • 8.死循环和目标机进行通信
  • 9.关闭套接字
  • 10.关于版本

1. 导入winsock.h库函数

#include<winsock.h>

2. 创建套接字

因为我们需要和客户端进行连接,所以既要创建服务端套接字,也要创建接收端套接字

SOCKET s_socket;
SOCkET s_accept;

3. 定义服务端地址和端口

 SOCKADDR_IN server_addr;
 server_addr.sin_family = AF_INET; //指定地址族为IPV4
 server_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);// Host to network long  INADDR_ANY对应0.0.0,0
 server_addr.sin_port = htos(5010)// Host to newtwork short 设置端口

4. 绑定端口和地址

if(bind(s_server, (SOCKADDR*)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR)
{
	cout<<"绑定失败"<<endl;
	WSACleanup();
	return;
}
cout<<"绑定成功"<<endl;

5. 开始监听

if(listen(s_server, SOMAXCONN) < 0)
{
	cout<<"开启监听失败"<<endl;
	WSACleanup();
	return;
}
cout<<"开启监听成功"<<endl;

6. 创建接收套接字地址

当客户端与服务端进行连接时,需要创建里一个套接字地址来进行接收

SOCKADDR accept_addr;

7.接收套接字建立连接

int len = sizeof(SOCKADDR)
s_accept = accept(s_server, (SOCKADDR*)&accept_addr, &sizeof(SOCKADDR));
 if(s_accept == SOCKET_ERROR)
    {
        cout<<"建立连接失败";
        WSACleanup();
        return;
    }
        cout<<"建立连接成功"<<endl<<"准备接受数据";

8.死循环和目标机进行通信

 while(true)
     {
         recv_len = recv(s_accept, recv_buf, 1024, 0);
         if(recv_len < 0)
         {
             cout << "接受失败" <<endl;
             break;
         }
         else{
             cout << "客户信息:" << endl << recv_buf << endl;
         }
        string s= "HTTP/1.1 200 OK\nContent-Type: text/html; charset=UTF-8\nConnection: keep-alive\nCache-Control: no-store, no-cache, must-revalidate\nPragma: no-cache\nContent-Length: ";
         String data = "<h1>Hello C++ Socket</h1>";
         s = s + data.length() + "\n\n" + data ;
		strcpy(send_bug, s.c_str());
         memcpy(send_buf, ptr, 1024);
         send_len = send(s_accept, send_buf, 1024, 0);
         if(send_len < 0)
         {
             cout << "发送失败" << endl;
             break;
         }
     }

9.关闭套接字

closesocket(s_server);
closesocket(s_accept);
WSACleanup();
retrun;

10.关于版本

当socket版本不符合时,是不能通信的
这就需要在通信前检测版本是否符合

void checkVision()
{
    WORD w_req = MAKEWORD(2, 2);
    WSADATA wsadata;
    int err;
    err = WSAStartup(w_req, &wsadata);
    if(err!=0)
    {
       cout<<"初始化套接字库失败";
    }
    else
    {
        cout<<"初始化套接字库成功";
    }
    // 检测版本号
    if(LOBYTE(wsadata.wVersion)!= 2|| HIBYTE(wsadata.wHighVersion)!=2 )
    {
        cout<<"套接字库版本号不符合";
         WSACleanup();
    }
    else
    {
        cout<<"套接字库版本正确";
    }
}

整体代码
使用的编译器是QtCraete,就简单使用qDebug来进行打印输出了

#include "selfsocket.h"
SelfSocket::SelfSocket()
{
    WORD w_req = MAKEWORD(2, 2);
    WSADATA wsadata;
    int err;
    err = WSAStartup(w_req, &wsadata);
    if(err!=0)
    {
       qDebug()<<"初始化套接字库失败";
    }
    else
    {
        qDebug()<<"初始化套接字库成功";
    }
    // 检测版本号
    if(LOBYTE(wsadata.wVersion)!= 2|| HIBYTE(wsadata.wHighVersion)!=2 )
    {
        qDebug()<<"套接字库版本号不符合";
         WSACleanup();
    }
    else
    {
        qDebug()<<"套接字库版本正确";
    }
}
void SelfSocket::Init()
{
    //创建套接字
    SOCKET s_server;
    SOCKET s_accept;
    s_server = socket(AF_INET, SOCK_STREAM, 0);// param: 协议族,协议类型,协议编号
    //创建长度
    int send_len, recv_len, len = 0;
    // 创建接受和发送缓存区
    char send_buf[1024];
    char recv_buf[1024];
    // 填充服务端信息:端口,地址
    SOCKADDR_IN server_addr;
    SOCKADDR_IN accept_addr;
    server_addr.sin_family = AF_INET; //指定地址族为IPV4
    server_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);// Host to network long  INADDR_ANY对应0.0.0,0
    server_addr.sin_port = htons(5010);// Host to network short
    // 套接字绑定
    if(bind(s_server,(SOCKADDR *)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR){
        qDebug()<<"套接字绑定失败";
        WSACleanup();
        return;
    }
    qDebug()<<"套接字绑定成功";
    // 开启监听
    if(listen(s_server, SOMAXCONN) < 0)
    {
        qDebug()<<"监听开启失败";
        WSACleanup();
        return;
    }
    qDebug()<<"开启监听"<<endl<<"服务器监听连接中>>:";
    // 接受连接请求
    len = sizeof(SOCKADDR);
    s_accept = accept(s_server,(SOCKADDR*)&accept_addr, &sizeof(SOCKADDR));
    if(s_accept == SOCKET_ERROR)
    {
        qDebug()<<"建立连接失败";
        WSACleanup();
        return;
    }
        qDebug()<<"建立连接成功"<<endl<<"准备接受数据";
     while(true)
     {
         recv_len = recv(s_accept, recv_buf, 1024, 0);
         if(recv_len < 0)
         {
             qDebug()<<"接受失败"<<endl;
             break;
         }
         else{
             qDebug()<<"客户信息:"<<recv_buf << endl;
         }
         QString s= "HTTP/1.1 200 OK\nContent-Type: text/html; charset=UTF-8\nConnection: keep-alive\nCache-Control: no-store, no-cache, must-revalidate\nPragma: no-cache\nContent-Length: %1\n\n";
         QString data = "<h1>Hello C++ Socket</h1>";
         s += data;
         s = s.arg(data.length());
         qDebug()<<s.toLocal8Bit().data()<<endl;

         QByteArray qb = s.toLatin1();
         char *ptr;
         ptr = qb.data();

         memcpy(send_buf, ptr, 1024);
         send_len = send(s_accept, send_buf, 1024, 0);
         if(send_len < 0)
         {
             qDebug()<<"发送失败"<<endl;
             break;
         }
     }
     // 关闭套接字
     closesocket(s_server);
     closesocket(s_accept);
     WSACleanup();
     return;
}


运行后在浏览器输入:localhost:5010就能展示成功
在这里插入图片描述
在这里插入图片描述

相关文章:

  • 做一个物联网温湿度传感器(一)SHT30传感器介绍
  • Sublime Text 最简单的更换主题和字体颜色的办法
  • 通过vue ui方式构建vue+electron项目
  • 2022最新一线大厂Java八股文合集PDF版震撼开源,堪称史上最强
  • 5.13一行代码就能解决的算法题
  • 序列查询新解
  • 5.10如何调度考生的座位
  • 基于retas的动漫动画制作与设计
  • 【Lua 入门基础篇(十)】文件I/O
  • Git 详细教程之五:SSH 免密登陆 GitHub
  • 单元测试啊
  • DolphinScheduler实例表备份、清理
  • java基于springboot+vue+elementui的校园志愿者活动管理系统
  • win7系统的两种硬盘格式mbr和gpt怎么选择?
  • (附源码)springboot课程在线考试系统 毕业设计 655127
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • [ JavaScript ] 数据结构与算法 —— 链表
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • 4. 路由到控制器 - Laravel从零开始教程
  • C++11: atomic 头文件
  • chrome扩展demo1-小时钟
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • Java深入 - 深入理解Java集合
  • Laravel 实践之路: 数据库迁移与数据填充
  • LeetCode刷题——29. Divide Two Integers(Part 1靠自己)
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • mysql中InnoDB引擎中页的概念
  • Python十分钟制作属于你自己的个性logo
  • Redis 懒删除(lazy free)简史
  • 阿里云应用高可用服务公测发布
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 免费小说阅读小程序
  • Java性能优化之JVM GC(垃圾回收机制)
  • #pragma pack(1)
  • #QT(一种朴素的计算器实现方法)
  • #传输# #传输数据判断#
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (LeetCode 49)Anagrams
  • (rabbitmq的高级特性)消息可靠性
  • (机器学习的矩阵)(向量、矩阵与多元线性回归)
  • (免费领源码)Python#MySQL图书馆管理系统071718-计算机毕业设计项目选题推荐
  • (十八)三元表达式和列表解析
  • (原)本想说脏话,奈何已放下
  • (转)详解PHP处理密码的几种方式
  • .h头文件 .lib动态链接库文件 .dll 动态链接库
  • .NET 中的轻量级线程安全
  • .NET命名规范和开发约定
  • .net中的Queue和Stack
  • @开发者,一文搞懂什么是 C# 计时器!
  • [ 常用工具篇 ] AntSword 蚁剑安装及使用详解
  • [@Controller]4 详解@ModelAttribute
  • [Android] 修改设备访问权限