服务器搭建(TCP套接字)-基础版(服务端)

news2024/11/25 14:29:10

在这里插入图片描述

一、socket

在这里插入图片描述

1.1、vim man查看socket

:!man socket

在这里插入图片描述
在这里插入图片描述

1.2、 依赖的头文件

 #include <sys/types.h>     
 #include <sys/socket.h>

1.3、原型

int socket(int domain, int type, int protocol);
domain说明
AF_INETIPV4协议
AF_INET6IPV6协议
AF_LOCALUnix域协议
type说明
SOCK_STREAM字节流套接字(TCP/SCTP)
SOCK_DGRAM数据报套接字(UDP)
SOCK_RAM原始套接字 (IPv4/IPv6)
SOCK_SEQPACKET有序分组套接字(SCTP)
protocol说明
IPPROTO_CPTCP传输协议
IPPROTO_UDPUDP传输协议
IPPROTO_SCTPSCTP传输协议

socket函数在成功时会返回一个小的非负整数值,它与文件描述符类似,就称它为套接字描述符。只需要指定协议族(IPV4、IPV6或Unix)和套接字类型即可

  • 代码实现
socket_fd=socket(AF_INET,SOCK_STREAM,0);

二、bind

在这里插入图片描述

2.1、 原型

int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
  • sockfd
    该参数为成功创建socket返回的套接字描述符

  • addr
    该参数为通用的套接字地址结构,套接字地址结构总是以引用形式来传递
    IPv4套接字地址结构
    IPv4套接字地址结构通常也称为“网际套接字地址结构”,它以sockaddr_in命名,定义在<netinet/in.h>头文件中。

struct sockaddr_in {
    short sin_family;        // 地址家族,一般为AF_INET
    unsigned short sin_port; // 端口号
    struct in_addr sin_addr; // IPv4地址
    char sin_zero[8];        // 填充字节,通常为0
};

sockaddr_in结构体定义了套接字的IPv4地址信息。它具有以下字段:

sin_family:指定地址家族,通常为AF_INET表示IPv4地址族。
sin_port:表示端口号,使用无符号短整数(16位)表示,需要以网络字节顺序(大端序)进行表示。
sin_addr:struct in_addr类型的结构体,用于表示IPv4地址。
sin_zero:用于填充字段,通常为0,以确保结构体的大小与sockaddr一致。

struct in_addr {
    unsigned long s_addr; // IPv4地址,以网络字节顺序(大端序)表示
};
#define PORT 8596
struct sockaddr_in local_addr;

 //set socket address
  local_addr.sin_family=AF_INET;
  local_addr.sin_port=htons(PORT);
  local_addr.sin_addr.s_addr=INADDR_ANY;
  bzero(&(local_addr.sin_zero),8);

htons:
头文件

#include <arpa/inet.h>

原型

uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

在这些函数的名字当中,h代表host,n代表network,s代表short,l代表long。

  • addrlen
    socklen_t 是一个在网络编程中使用的类型,用于表示套接字地址结构的长度

2.2、代码

#define PORT 8596
struct sockaddr_in local_addr;
//set socket address
  local_addr.sin_family=AF_INET;
  local_addr.sin_port=htons(PORT);
  local_addr.sin_addr.s_addr=INADDR_ANY;
  bzero(&(local_addr.sin_zero),8);
 //bind socket
 ret=bind(socket_fd, (struct sockaddr *)&local_addr,sizeof(struct sockaddr_in));
 if(ret == -1){
    perror("bind socket error");
    exit(1);
 }

三、listen

在这里插入图片描述

3.1、原型

int listen(int sockfd, int backlog);
  • sockfd
    该参数为成功创建socket返回的套接字描述符
  • backlog
      在网络编程中使用的参数,用于指定监听套接字(listening socket)上挂起连接请求的队列的最大长度。
      在 TCP/IP 网络编程中,当服务器应用程序使用 listen 函数将套接字设置为监听模式时,内核会创建一个连接队列来存储客户端发起的连接请求。
      backlog 参数用于指定这个连接队列的最大长度,即可以挂起等待被接受的连接请求数量。具体来说,当有新的连接请求到达监听套接字时,如果连接队列未满,内核会将该连接请求添加到队列中,并发送一个 SYN+ACK 响应给客户端。如果连接队列已满,则客户端的连接请求可能会被忽略或拒绝。
      只影响处于未接受状态的连接请求,在已经接受的连接请求上没有影响。一旦服务器应用程序调用 accept 函数接受了一个连接请求,该连接就会从队列中移除。

3.2、代码

ret=listen(socket_fd, backlog);
if(ret ==-1){
   perror("listen error");
   exit(1);
  }

四、accept

在这里插入图片描述

4.1、原型

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

  accept 是一个在网络编程中使用的函数,用于接受客户端的连接请求并创建与客户端连接的套接字。
  accept 函数通常在服务器端使用,它从监听套接字(listening socket)的连接队列中取出一个连接请求,并创建一个新的套接字来与客户端进行通信。这个新创建的套接字可以用于与客户端进行数据交换。

入参:

  • sockfd:整型参数,表示监听套接字的文件描述符
  • addr:指向 struct sockaddr 类型的指针,用于存储连接的客户端地址信息。可以传入 NULL,表示不获取客户端地址信息。
  • addrlen:指向 socklen_t 类型的指针,用于传入客户端地址结构的长度,并在函数调用后被修改为实际的客户端地址结构长度。

返回值:

  • 如果成功接受连接请求,accept 返回一个新的套接字的文件描述符,该套接字用于与客户端进行通信。
  • 如果发生错误,accept 返回 -1,并设置相应的错误码,可以通过 errno 全局变量获取具体的错误信息。

4.2、代码

struct sockaddr_in remote_addr;
int accept_fd=-1;

socklen_t addrlen = sizeof(remote_addr);
accept_fd=accept(socket_fd,( struct sockaddr *)&remote_addr, &addrlen);

五、recv

在这里插入图片描述

5.1、原型

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

recv 是一个在网络编程中使用的函数,用于接收数据从已连接的套接字或接收数据报套接字中。

需要注意的是,recv 函数是一个阻塞调用,即在没有数据到达之前,它会一直等待。如果需要非阻塞的操作,可以使用非阻塞 I/O 或多线程/多进程的方式处理接收操作。

入参:

  • sockfd:整型参数,表示要接收数据的套接字的文件描述符。
  • buf:指向接收数据缓冲区的指针,用于存储接收到的数据。
  • len:无符号整型参数,表示接收数据缓冲区的长度。
  • flags:整型参数,用于指定接收操作的可选标志。常见的标志包括 0(无特殊标志)、MSG_DONTWAIT(非阻塞模式接收)和 MSG_WAITALL(阻塞模式接收,直到接收到指定长度的数据)等。

返回值:

  • 如果成功接收数据,recv 返回接收到的字节数。
  • 如果连接关闭(对于流套接字)或接收超时(对于数据报套接字),recv 返回 0。
  • 如果发生错误,recv 返回 -1,并设置相应的错误码,可以通过 errno 全局变量获取具体的错误信息。

5.2、代码

#define MESSAGE_SIZE 1024
int accept_fd=-1;
char in_buf[MESSAGE_SIZE]={0,};

memset(in_buf,0,MESSAGE_SIZE);
//read data
ret =recv(accept_fd, (void*)in_buf, MESSAGE_SIZE, 0);
if(ret ==0){
    break;
}
printf("receive data:%s\n",in_buf);

六、send

在这里插入图片描述

6.1、原型

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

send 是一个在网络编程中使用的函数,用于发送数据到已连接的套接字或发送数据报套接字中。

入参:

  • sockfd:整型参数,表示要发送数据的套接字的文件描述符。
  • buf:指向要发送数据的缓冲区的指针。
  • len:无符号整型参数,表示要发送数据的长度。
  • flags:整型参数,用于指定发送操作的可选标志。常见的标志包括 0(无特殊标志)和 MSG_DONTWAIT(非阻塞模式发送)等。

返回值

  • 如果成功发送数据,send 返回发送的字节数。
  • 如果连接关闭(对于流套接字)或发送超时(对于数据报套接字),send 返回 0。
  • 如果发生错误,send 返回 -1,并设置相应的错误码,可以通过 errno 全局变量获取具体的错误信息。

6.2、代码

#define MESSAGE_SIZE 1024
int accept_fd=-1;
char in_buf[MESSAGE_SIZE]={0,};

send(accept_fd, (void *)in_buf, MESSAGE_SIZE, 0);

七、完整代码

#include <iostream>
//socket
#include <sys/types.h>
#include <sys/socket.h>
//close
#include <unistd.h>
//exit
#include <stdlib.h>
//perror
#include <stdio.h>
//memset
#include <string.h>
//htons
#include <arpa/inet.h>

#define PORT 8596
#define MESSAGE_SIZE 1024

int main(){

  int ret=-1;
  int socket_fd=-1;
  int accept_fd=-1;
  int backlog=10;
  int flag=1;

  char in_buf[MESSAGE_SIZE]={0,};
  struct sockaddr_in local_addr,remote_addr;

  //create socket
  socket_fd=socket(AF_INET,SOCK_STREAM,0);
  if(socket_fd == -1){
    perror("create socket error");
    exit(1);
  }
 //set option of socket
  ret = setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
  if ( ret == -1 ){
    perror("setsockopt error");
  }
 //set socket address
  local_addr.sin_family=AF_INET;
  local_addr.sin_port=htons(PORT);
  local_addr.sin_addr.s_addr=INADDR_ANY;
  bzero(&(local_addr.sin_zero),8);
 //bind socket
 ret=bind(socket_fd, (struct sockaddr *)&local_addr,sizeof(struct sockaddr_in));
 if(ret == -1){
    perror("bind socket error");
    exit(1);
 }

  ret=listen(socket_fd, backlog);
  if(ret ==-1){
   perror("listen error");
   exit(1);
 }
  //loop to accept client
  for(;;){
   socklen_t addrlen = sizeof(remote_addr);
   accept_fd=accept(socket_fd,( struct sockaddr *)&remote_addr, &addrlen);
   for(;;){
     memset(in_buf,0,MESSAGE_SIZE);
     //read data
     ret =recv(accept_fd, (void*)in_buf, MESSAGE_SIZE, 0);
     if(ret ==0){
        break;
     }
     printf("receive data:%s\n",in_buf);
     send(accept_fd, (void *)in_buf, MESSAGE_SIZE, 0);
   }
   printf("close client connection......");
   close(accept_fd);
  }
  printf("quit server....");
  close(socket_fd);
  return 0;
}

八、编译

gcc baseServer.cpp -o server

在这里插入图片描述
gcc 默认不会自动链接 C++ 标准库,因此需要手动添加链接选项 -lstdc++ 来告知编译器链接 C++ 标准库。

gcc baseServer.cpp -o server -lstdc++

或者直接使用g++编译。

8.1、gcc和g++的区别

gcc 和 g++ 在功能上有一些区别,主要体现在它们的默认行为和对源代码的处理方式上。

1、默认语言:gcc 默认将源代码视为 C 语言源代码进行处理,而 g++ 默认将源代码视为 C++ 语言源代码进行处理。这意味着如果您使用 gcc 编译 C++ 代码,可能会导致一些 C++ 特定的功能和语法无法正常工作。

2、链接库:g++ 在链接时会自动包含 C++ 标准库(例如 libstdc++),而 gcc 则不会。这是因为 C++ 标准库包含了许多与 C++ 相关的功能和数据结构,而 C 标准库(例如 libc)则只包含了与 C 相关的功能。

3、标准支持:g++ 支持更多的 C++ 标准,例如 C++11、C++14、C++17 等。而 gcc 的 C 标准支持(例如 C89、C99)更全面,但对于最新的 C++ 标准可能支持较少。

4、编译选项:gcc 和 g++ 有一些针对特定语言的编译选项。例如,g++ 具有额外的选项来支持 C++ 异常处理、RTTI(运行时类型信息)等特性。

虽然 gcc 和 g++ 在默认行为和一些功能上有所区别,但它们都是 GNU 编译器套件的一部分,共享许多相同的代码和基础设施。实际上,g++ 实际上是一个对 gcc 进行了配置和扩展的别名。

在大多数情况下,如果您要编译 C 代码,可以使用 gcc。如果您要编译 C++ 代码,可以使用 g++,这样可以确保默认行为和所需的语言支持正确。 然而,您也可以使用 gcc 编译 C++ 代码,或者使用 g++ 编译 C 代码,只需根据需要适当调整编译选项和参数。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript中的垃圾回收机制

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ JavaScript的垃圾回收机制⭐ 内存管理⭐ 引用计数⭐ 标记-清除算法⭐ 内存泄漏⭐ 性能优化⭐ 使用delete操作符⭐ 注意循环中的变量引用⭐ 使用工具进行内存分析⭐ 使用合适的数据结构⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探…

企业架构LNMP学习笔记54

企业架构NoSQL数据库之MongoDB。 学习目标和内容&#xff1a; 1&#xff09;能够简单描述mongoDB的使用特点&#xff1a; 2&#xff09;能够安装配置启动MongoDB&#xff1b; 3&#xff09;能够使用命令行客户端简单操作MongoDB&#xff1b; 4&#xff09;能够实现基本的数…

vsftp3.0 匿名用户,本地用户,虚拟用户

整体配置介绍&#xff1a; 进入vsftpd配置文件 vim /etc/vsftpd/vsftpd.conf //输入i开始编辑&#xff0c;修改后按esc退出编辑&#xff0c;输入:wq后回车保存并退出anonymous_enableYES #接受匿名用户&#xff0c;默认无密码请求 lo…

01_Elasticsearch入门介绍

01_Elasticsearch入门介绍 Elasticsearch 是什么1、什么是搜索&#xff1f;2、如果用数据库做搜索会怎么样&#xff1f;3、什么是全文检索和Lucene&#xff1f;4、什么是Elasticsearch&#xff1f;5、Elasticsearch的功能6、Elasticsearch的适用场景7、Elasticsearch的特点 什么…

Anaconda成功安装之后没有在菜单列和桌面显示图标

1、进入命令提示符 2、输入cmd 3、进入到Anaconda安装路径 比如我装在F盘 4、然后输入 python .\Lib\_nsis.py mkmenus 回车 这时候菜单列就可以看到了

第 4 章 串(串的堆分配存储实现)

1. 背景说明 实现基本与定长分配一致&#xff0c;不过将定长分配改为动态分配&#xff0c;解除了长度限制&#xff0c;实现更加灵活。 2. 示例代码 1) status.h /* DataStructure 预定义常量和类型头文件 */#ifndef STATUS_H #define STATUS_H#define CHECK_NULL(pointer) if …

[JAVAee]spring-Bean对象的执行流程与生命周期

执行流程 spring中Bean对象的执行流程大致分为四步: 启动Spring容器实例化Bean对象Bean对象注册到Spring容器中将Bean对象装配到所需的类中 ①启动Spring容器,在main方法中获取spring上下文对象并配备spring. import demo.*;import org.springframework.context.Applicati…

nacos动态配置刷新机制原理

nacos动态配置刷新机制原理 项目里面许多业务场景以及灵活配置的需求经常要用到动态配置。一般就是apollo和nacos两种选型。 nacos动态刷新导致的bug nacos一般为了实现动态配置一般会加入RefreshScope注解进行实现&#xff0c;例如下面的代码加入了RefreshScope想要实现跨域…

智能家居监控管理系统项目需求分析

目录 一、引言 1、目的 2、背景 二、项目系统概述 1、项目产品概述 2、项目功能架构 3、项目市场需求 三、项目硬件需求 1、核心开发板 2、实时检测模块 3、实时信息交互模块 4、用户安全登录模块 5、开发板可扩展模块 6、硬件之间连接设备 四、项…

网络安全进阶学习第二十课——CTF之文件操作与隐写

文章目录 一、文件类型识别1、File命令2、Winhex3、文件头残缺/错误 二、文件分离操作1、Binwalk工具2、Foremost3、dd4、Winhex 三、文件合并操作1、Linux下的文件合并2、Windowsa下的文件合并 四、文件内容隐写Winhex 五、图片文件隐写1、图片混合2、LSB(最低有效位 Least Si…

slickEdit 2022 (v27.0.2)Ubuntu安装以及破解

1去官网下载安装包 SlickEdit 也可以从我这里下载源码包 https://download.csdn.net/download/m0_38012470/88343180 2.解压压缩包并进入根目录 3.sudo ./vsinst 4按住回车不松手一直到显示需要你输入yes的时候 5.一路通过需要输入Y的时候就输入 6.一直到弹出对话框关闭…

c++11的一些新特性

c11 1. {}初始化2. 范围for循环3. final与override4. 右值引用4.1 左值引用和右值引用4.2 左值引用与右值引用比较 5. lambda表达式6. 声明6.1 auto6.2 decltype6.3 nullptr 7. 可变参数模版 1. {}初始化 在C中&#xff0c;使用花括号初始化的方式被称为列表初始化。列表初始化…

Windows C++ 环境下 eigen、osqp、osqp-eigen安装教程

本文是Windows环境下安装eigen、osqp、osqp-eigen的一个简单教程。 osqp是用于二次规划的一种求解器&#xff0c;提供包括C、Matlab、Python等在内的接口&#xff0c;但是不包含C接口。为了能在C 中使用osqp&#xff0c;可以使用osqp-eigen接口进行调用。 第一步&#xff1a;…

第二章 进程与线程 七、处理机调度(概念、层次)

目录 一、基本概念 二、三个层次 1、高级调度&#xff08;作业调度&#xff09; 2、低级调度&#xff08;进程调度/处理机调度&#xff09; 3、中级调度&#xff08;内存调度&#xff09; 三、三次调度的联系、对比 四、七状态模型 五、总结 一、基本概念 当有一堆任务…

利用群论来研究魔方

文章灵感来源于&#xff1a; 魔方与群论&#xff08;二&#xff09;&#xff08;交换子牛啤&#xff01;&#xff09; - 知乎并参考了&#xff1a;https://www.gap-system.org/Doc/Examples/rubik.html使用了这里的小程序&#xff1a;Cubie 先汇制一张&#xff0c;魔方图 ----…

MySQL数据库upsert使用

本文翻译自&#xff1a;MySQL UPSERT - javatpoint&#xff0c;并附带自己的一些理解和使用经验. MySQL UPSERT UPSERT是数据库管理系统管理数据库的基本功能之一&#xff0c;它允许数据库操作语言在表中插入一条新的数据或更新已有的数据。UPSERT是一个原子操作&#xff0c;…

手刻 Deep Learning -第壹章-PyTorch入门教学-基础概念与再探线性回归

一、前言 本章会需要 微分、线性回归与矩阵的基本观念 这次我们要来做 PyTorch 的简单教学&#xff0c;我们先从简单的计算与自动导数&#xff08; auto grad / 微分 &#xff09;开始&#xff0c;使用优化器与误差计算&#xff0c;然后使用 PyTorch 做线性回归&#xff0c;还有…

office mac苹果办公软件安装包安装教程详解

软件下载 软件&#xff1a;mac office版本&#xff1a;2021语言&#xff1a;简体中文大小&#xff1a;4.27G安装环境&#xff1a;mac硬件要求&#xff1a;CPU2.0GHz 内存4G(或更高&#xff09;下载通道 百度网盘 https://pan.baidu.com/s/1WGSB-icELUxweFkI8iIbzA 首先&#…

恒源云GPU使用tensorboard || 以OpenMMLab系列为例 || 定时复制可视化日志

序言 在训练过程中使用可视化工具向来是很有效的。相比于shell中的输出&#xff0c;可视化能够更好地向我们展现在训练过程中各项指标的变化。 但是&#xff0c;由于深度学习所需要的设备性能要求较高&#xff0c;我们常常使用云GPU进行训练。但是一些云平台的可视化工具让人摸…

2023国赛B题:多波束测线问题 评阅要点完整分析

本文所有分析仅代表个人观点&#xff0c;不代表官方&#xff0c;仅供参考 制作人&#xff1a;川川徒弟 demoo CSDN&#xff1a;川川菜鸟公众号&#xff1a;川川带你学AI 全文采用非编程做法  需要工具&#xff1a; geogebra、matlab工具箱   注&#xff1a; 本文全文不考虑…