c++ socket、 listen、accept、recv 、send、 connect函数记录

2023-11-10

socket

int socket (int __domain, int __type, int __protocol);
  1. __domain为协议域,又称协议族,我们最常用的有AF_INET、AF_INET6(也可以写作为PF_INET、PF_INET6),分别代表IPv4地址和IPv6地址。

  2. __type为数据传输方式或套接字类型,最常见的有SOCK_STREAM和 SOCK_DGRAM,其中SOCK_STREAM为面向连接的数据传输方式,是基于TCP的协议,数据可以准确无误地到达另一台计算机,如果损坏或丢失,可以重新发送,但效率相对较慢;而SOCK_DGRAM是无连接的数据传输方式,是基于UDP的协议,即只管传输数据,不作数据校验,如果数据在传输中损坏,或者没有到达另一台计算机,是没有办法补救的。

  3. __protocol为传输协议,对应上述的__type,常用的有IPPROTO_TCP 和 IPPTOTO_UDP分别代表TCP和UDP协议。而系统会根据__type的值自行选择,因此该项一般可直接指定为0。

  4. socket返回的值是一个文件描述符,由于0,1,2,都被占用,所以是从3开始,错误时返回-1;

bind()和connect()函数

bind()函数用于服务器端,用来绑定套接字和自己的ip地址和端口;
connect()函数用于客户端,旨在连接套接字和服务器端的IP地址和端口。
两个函数的返回值表示是否成功(0表示成功,-1表示错误)
函数原型如下:

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
  1. sockfd为socket返回的文件描述符。

  2. addr为一个const struct sockaddr *指针,由于兼容性的原因,这里我们只能先使用sockaddr_in 结构体来定义相应的IP地址和端口号,然后再强制转换为 sockaddr 类型的方式。

  3. addrlen为2中结构体的大小,可由sizeof()计算给出。

在使用上述两个函数之前,需要先给sockaddr_in 结构体中的成员赋值,其中sockaddr_in 结构体的成员变量如下:

struct sockaddr_in{
    sa_family_t     sin_family;   //协议族,和socket()函数中一致即可
    uint16_t        sin_port;     //16位的端口号,尽量保证端口号在1024~65536之间
    struct in_addr  sin_addr;     //32位IP地址
    char            sin_zero[8];  //不使用,一般用0填充
};

listen()和accept()函数

在服务器端,绑定了套接字后,还需通过listen()函数进入到监听状态。
监听状态下调用accept()函数进行接收,当收到来自客户端的请求后就可以建立连接了。
listen()函数返回值0表示成功,-1表示失败

int listen(int __fd, int __n);
  1. __fd为socket返回的文件描述符。

  2. __n为请求队列的最大长度,也即缓冲区大小。当socket正在处理客户端请求时,如果有新的请求到来,只能被放进缓冲区,这个参数就是表明能接受多少个客户端请求。

accept()函数返回一个新的文件描述符,表示和对应的客户端进行通信。

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  1. __fd为socket返回的文件描述符。

  2. addr为一个const struct sockaddr *指针,由于兼容性的原因,这里我们只能先使用sockaddr_in 结构体来定义相应的IP地址和端口号,然后再强制转换为 sockaddr 类型的方式。

  3. addrlen为一个指针,解引用后值为2中结构体的大小,可由sizeof()计算给出。

send()、recv()、read()和write()函数

send()和write()返回值为向fd写入的字节数,=0时断开连接,<0时出错。
recv()和read()返回值为从fd读取的字节数,=0时断开连接或读取结束,<0时出错。

ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void*buf,size_t nbytes);
  • read:负责从描述符fd中读取内容,当读取成功时,read返回实际所读的字节数(大于0);如果返回的值为0,表示已经读到文件结束了;如果返回的值小于0,则出现错误,如果错误为EINTR,说明错误是由中断引起的,如果是ECONNREST表示网络连接出了问题。

  • write:将buf中的nbytes字节内容写入到文件描述符fd,成功时返回写的字节数,失败的时候返回-1;在实际的程序中,写入有两种可能:

    • write的返回值大于0,表示写了部分或者是全部的数据。这样我们用一个while循环来不停的写入,但是循环过程中的buf参数和nbyte参数得由我们来更新。也就是说,网络写函数是不负责将全部数据写完之后在返回的。
    • 返回的值小于0,此时出现了错误。我们要根据错误类型来处理.如果错误为EINTR表示在写的时候出现了中断错误。如果为EPIPE表示网络连接出现了问题(对方已经关闭了连接).
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t recv(int sockfd, void *buf, size_t len, int flags);

第四个参数可以是

flags 描述
MSG_DONTROUTE 不查找表
MSG_OOB 接受或者发送带外数据
MSG_PEEK 查看数据,并不从系统缓冲区移走数据
MSG_WAITALL 等待所有数据

当recv/send的flag参数设置为0时,则和read/write是一样的。
如果有如下几种需求,则read/write无法满足,必须使用recv/send:

  • 为接收和发送进行一些选项设置
  • 从多个客户端中接收报文
  • 发送带外数据(out-of-band data)

TCP客户端

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<netdb.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>

using namespace std;

int main(int argc, char *argv[]){
    if(argc!=3){
        cout<<"Example:./myTceClient 127.0.0.1 5005"<<endl;
    }

    int sockfd;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd==-1){
        perror("socket");
        return -1;
    }

    struct hostent *h;
    if((h=gethostbyname(argv[1])) == 0){
        cout<<"gethostbyname failed"<<endl;
        close(sockfd);
        return -1;
    }

    // struct hostent  {  
    //     char *h_name;         //正式主机名  
    //     char **h_aliases;     //主机别名  
    //     int h_addrtype;       //主机IP地址类型:IPV4-AF_INET  
    //     int h_length;         //主机IP地址字节长度,对于IPv4是四字节,即32位  
    //     char **h_addr_list;   //主机的IP地址列表  
    // }; 


    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(atoi(argv[2]));
    memcpy(&servaddr.sin_addr, h->h_addr, h->h_length);

    int conres = connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
    if(conres != 0){
        perror("connect failed");
        close(sockfd);
        return -1;
    }

    char buffer[1024];

    for(int ii=0; ii<3; ii++){
        int iret;
        memset(buffer,0, sizeof(buffer));
        sprintf(buffer, "this is  test");
        iret = send(sockfd, buffer, strlen(buffer),0);
        if(iret<=0){
            perror("send");
            break;
        }
        cout<<buffer<<endl;
        memset(buffer,0,sizeof(buffer));

        iret = recv(sockfd, buffer, sizeof(buffer), 0);
        if(iret<=0){
            cout<<"recv nothing"<<endl;
            break;
        }
        cout<<"recv="<<buffer<<endl;
    }
    close(sockfd);
    return 0;
}

Tcp服务端

#include<iostream>
#include<bits/stdc++.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<netdb.h>
#include<arpa/inet.h>
#include<sys/socket.h>
using namespace std;
int main(int argc, char *argv[] ){
	if(argc!=2){
	cout<<"Example:./myTcpServer 5005 "<<endl;
	return -1;
	}
	int listenfd;
	listenfd = socket(AF_INET, SOCK_STREAM, 0);
	if(listenfd==-1){
		perror("socket");
		return -1;	
	}
	struct sockaddr_in servaddr;
	memset(&servaddr, 0, sizeof(servaddr));
	
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(atoi(argv[1]));
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

	int bres=bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
	if(bres!=0){
		perror("bind");
		close(listenfd);
		return -1;
	}

	int lisres = listen(listenfd, 5);
	if(lisres != 0){
		perror("listen");
		close(listenfd);
		return -1;
	}

	int clientfd;
	int socklen=sizeof(struct sockaddr_in);
	struct sockaddr_in clientaddr;
	clientfd = accept(listenfd, (struct sockaddr *)&clientaddr, (socklen_t*)&socklen);
	cout<<"客户端"<<inet_ntoa(clientaddr.sin_addr)<<"已连接"<<endl;

	char buffer[1024];
	while(true){
		int iret;
		memset(buffer,0,sizeof(buffer));
		iret = recv(clientfd, buffer, sizeof(buffer), 0);
		if(iret<=0){
			cout<<"iret="<<iret<<endl;
			break;
		}
		cout<<"message="<<buffer<<endl;
		
		strcpy(buffer, "ok");
		iret = send(clientfd,buffer,strlen(buffer),0);
		if(iret<=0){
			perror("sent");
			break;
		}
		cout<<"发送:"<<buffer<<endl;
		
	}
	close(listenfd);
	close(clientfd);

	return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c++ socket、 listen、accept、recv 、send、 connect函数记录 的相关文章

  • 不同提供商的相同 EDMX 文件

    我正在开发一个项目 其中有一个本地数据库 SQL CE 在不存在与服务器的连接的情况下用作缓冲区 在服务器上我想使用相同的数据库布局 当然 我想使用服务器和客户端上可用的 Common dll 中的相同 EDMX 文件 在客户端中 我有一个
  • 使用sqlbulkcopy之前如何创建表

    我有一个 DBF 文件 我正在尝试导入该文件 然后将其写入 SQL 表 我遇到的问题是 如果我使用 SqlBulkCopy 它需要我提前创建表 但在我的场景中这是不可能的 因为 dbf 文件不断变化 到目前为止 这是我的代码 public
  • 显示 div 内的用户名列表

    我是 jQuery 新手 在我的项目中 我创建了一个类User其中代码如下所示 static ConcurrentDictionary
  • C++ 中的“int”默认是“signed long int”吗?

    Is int默认情况下signed long int in C 它是否依赖于平台和 或编译器 如果是这样 怎么办 EDIT 以下任何一项是否保证是重复的 signed short int signed int signed long int
  • 无需登录即可在 Intranet 上获取 Web 应用程序的域\用户名

    我的 Intranet 上有一个 Web 应用程序 VS 2005 有几个页面不需要用户登录应用程序 反馈和默认页面 我正在尝试获取要显示和 或发送反馈的域名和用户名 有没有一种方法可以在不需要用户登录的情况下执行此操作 我试过了this
  • 如何检查号码是否只有唯一的数字?

    例如 2345 是唯一的数字 因为没有数字显示两次 但 3324 不是唯一的数字 因为 3 出现了两次 我尝试使用 但我 代码 显示但我没有得到数字我得到了数字 编辑 你不能使用字符串 number 10 number 100 number
  • 如何部署包含第三方 DLL 文件的 C# 应用程序?

    首先 我对部署了解不多 我希望我的问题有意义 我需要将 C 应用程序安装 部署到多个桌面 它需要一个第三方 DLL 文件 一个 C 库 lpsolve55 dll 对于那些感兴趣的人 它是一个免费的 MIP LP 求解器 请参阅 lpsol
  • 尽管浮点数相同,但它们并不相等? [复制]

    这个问题在这里已经有答案了 下面的程序输出This No is not same 当两个数字相同时为什么会这样做 void main float f 2 7 if f 2 7 printf This No is same else prin
  • 如何从 C# 调用 F# 类型扩展(静态成员函数)

    FSharp 代码的结构如下 我无法控制源代码 namespace FS
  • 为什么我在 WinForms 列表框中得到“System.Data.DataRowView”而不是实际值?

    每当我运行代码并尝试查看highscore我在列表框中得到的只是System Data DataRowView 谁能明白为什么吗 Code MySqlConnection myConn new MySqlConnection connStr
  • C#生成的csv文件通过电子邮件发送嵌入到Lotus Note中电子邮件的底部

    我遇到了一个奇怪的问题 即使用 NET SmtpClient 通过电子邮件发送的 CSV 附件出现在电子邮件底部 而不是 Lotus Note 中的附件 我只是不知道如何解决这个问题 而且我无法访问客户端计算机 这使得调试非常困难 我可以采
  • 原子的 C++ 内存屏障

    在这方面我是个新手 谁能提供以下内存屏障之间差异的简化解释 窗户MemoryBarrier 围栏 mm mfence 内联汇编asm volatile memory 内在的 ReadWriteBarrier 如果没有简单的解释 一些好文章或
  • 如果我重新分配并且新大小为 0,会发生什么情况。这与释放等效吗?

    给出以下代码 int a NULL a calloc 1 sizeof a printf d n a a realloc a 0 printf d n a return 0 它返回 4078904 0 这个 realloc 相当于 free
  • 如果项目包含多个文件夹,如何使用 Add-Migration

    我想Add Migration使用我的 DbContext 但出现错误 The term add migration is not recognized as the name of a cmdlet function script fil
  • 使用联合对 IP 地址进行多种解释?

    在工作中 我们使用以下构造来将 IP 地址解释为 4 字节数组或 32 位整数 union IPv4 std uint32 t ip std uint8 t data 4 这很好用 但是读完这本书的第 97 章 不要使用联合来重新解释表示
  • 删除数组时出现访问冲突异常

    删除分配的内存时 出现 访问冲突读取位置 异常 如下所示 我有一个针对 Visual Studio 2010 工具集 v100 C 编译器编译的本机 dll 我有一个针对它的托管 dll 包装器 它是针对工具集 v90 编译的 因为我想以
  • 文本框中“结束编辑”的事件

    我正在 winform c 中使用文本框 并使用文本在数据库中进行查询 但每次文本更改时 我都需要不断查阅文本框的文本 因此 对于这些 我使用 KeyUp 但这个活动太慢了 文本框编辑完成后是否会触发任何事件 我考虑完成2个条件 控制失去焦
  • 如何使 WinForms UserControl 填充其容器的大小

    我正在尝试创建一个多布局主屏幕应用程序 我在顶部有一些按钮链接到应用程序的主要部分 例如模型中每个实体的管理窗口 单击这些按钮中的任何一个都会在面板中显示关联的用户控件 面板包含用户控件 而用户控件又包含用户界面 WinForms User
  • C# 模式匹配

    我对 C 有点陌生 我正在寻找一个字符串匹配模式来执行以下操作 我有一个像这样的字符串 该书将在 唐宁街 11 号接待处 并将由主要医疗保健人员参加 我需要创建一个 span 标签来使用 startIndex 和 length 突出显示一些
  • boost::spirit::qi::语法和可变参数模板

    我在使用可变参数模板定义语法时面临一个问题 我首先定义一些包含在某些结构中的简单语法 例如纬度 经度 如下所示 include

随机推荐

  • win下从NUMA节点分配内存

    微软官网链接 https docs microsoft com zh cn windows win32 memory allocating memory from a numa node redirectedfrom MSDN 示例代码 d
  • Java高级教程

    Java高级教程 Java11文档 Java数据结构 Java工具包提供了强大的数据结构 在Java中的数据结构主要包括以下几种接口和类 枚举 Enumeration 位集合 BitSet 向量 Vector 栈 Stack 字典 Dict
  • Error loading workspace: You are outside of a module and outside of $GOPATH/src. If you are using mo

    1 描述 如果你使用vsCode去编译 go 项目的时候 出现这个错误 那么并不是你的go moudle 除了问题 同时你会发现执行Run Code也是执行失败的 2 原因 你的工作区默认是项目根目录 但你单开的文件并不是项目根目录 3 解
  • lvgl8.2 img 图片显示

    1 lvgl 图片显示源 为了提供良好的图片显示灵活性 所以显示图像的来源可以是以下三种 代码中的一个变量 一个带有像素颜色数据的 C 数组 存储在外部的文件 比如 SD 卡 带有符号的文本 2 内部图片 对于源码内部图片 将图片转换为图片
  • 前端自动化测试——vue单元测试vue-test-utils

    自动化测试分类 单元测试 单元测试 unit testing 是指对软件中的最小可测试单元进行检查和验证 简单来说 单元就是人为规定的最小的被测功能模块 可能是一个单一函数或方法 一个完整的组件或类 单元测试是最小巧也是最简单的测试 它们通
  • paddlelite编译python版: FIND_PACKAGE called with invalid argument或者fatal: no tag exactly matches 。【已解决】

    报错1 不是这个原因 这个错误不会影像编译 fatal no tag exactly matches 518238f89e84868d666b5cbe6860788934f290d7 tag branch develop commit 51
  • TCP flag注释

    http blog csdn net wisage article details 6049733 三次握手Three way Handshake 一个虚拟连接的建立是通过三次握手来实现的 1 B gt SYN gt A 假如服务器A和客户
  • 【华为OD机试】寻找相同子串(C++ Python Java)2023 B卷

    时间限制 C C 1秒 其他语言 2秒 空间限制 C C 262144K 其他语言524288K 64bit IO Format lld 语言限定 C clang11 C clang 11 Pascal fpc 3 0 2 Java jav
  • 若依系统(Ruoyi-Vue)去除redis数据库

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 目的 一 去除redis 配置 二 去除ruoyi framework下RedisConfig的配置 三 在ruoyi common的core redis下新建My
  • 领域驱动设计-Domain-Driven-Design概念

    2021了 你应该要了解DDD了 不然领导和你吹牛你都听不懂 或者你都没法和别人吹牛了 一 Evans DDD 是什么 1 1 背景 2002年 敏捷宣言诞生 时代处于 CS 到 BS 的转换时期 2003年 Eric Evans 发表 l
  • angular?!小白修仙之路……

    一 简介 Angular是一个功能非常完备的前端框架 最早由 Misko Hevery 等人创建 2009 年被Google 公式收购 用于其多款产品 Angular基于TypeScript 通过增强HTML的方式提供一种便捷开发Web应用
  • 【100%通过率 】【华为OD机试 c++ 】不含 101 的数【2023 Q1

    华为OD机试 题目列表 2023Q1 点这里 2023华为OD机试 刷题指南 点这里 题目描述 小明在学习二进制时 发现了一类不含 101的数 也就是 将数字用二进制表示 不能出现 101 现在给定一个整数区间 l r 请问这个区间包含了多
  • 【python 多线程存数据lock(锁)】

    多线程存数据不会数据丢失 案例一 这里只是简单的线程池 import os from concurrent futures import ThreadPoolExecutor from time import perf counter im
  • PTA-计算工资

    计算工资 某公司员工的工资计算方法如下 一周内工作时间不超过40小时 按正常工作时间计酬 超出40小时的工作时间部分 按正常工作时间报酬的1 5倍计酬 员工按进公司时间分为新职工和老职工 进公司不少于5年的员工为老职工 5年以下的为新职工
  • TypeScript 之类型判断

    在使用 Angular 做项目的时候 对 TypeScript 的类型判断不太熟练 为了方便查找 特意对 TypeScript 的类型判断做了简单梳理 文章只是 TS 官网的内容摘要 没有高深的知识 想要深入学习 TS 还要看官网文档 基础
  • 18M 超轻量系统开源

    图像识别作为深度学习算法的主流实践应用方向 早已在生活的各个领域发挥作用 如安全检查和身份核验时的人脸识别 无人货架和智能零售柜中的商品识别 这些任务背后的关键技术都在于此 图1 PP ShiTu应用于商品识别效果示意 开发者应用展示 然而
  • JMeter压测原则之独立部署监控

    无论是用哪种压测工具 我们都会比较关心压测工具所在机器的的系统资源占用情况 毕竟很多人压着压着 压力机出现性能瓶颈了还不知道 并且还错误的评估成是被测系统的性能问题 很多初学者好像都犯过这种尴尬的错误 文章分成三个部分说明 为什么说Perf
  • a &a &a[0]之间的区别和联系

    数组中 a为数组的首地址 a 0 为数组第一个元素的地址 所以 a a 0 但是 a又是什么东西呢 我们来做下面的代码测试 include
  • Binary operator ‘==‘ cannot be applied to operands of type ‘Int‘ and ‘[Int]‘

    等号两边数据类型不一致进行比较报错 Binary operator cannot be applied to operands of type Int and Int 这个提示也挺明确 二元运算符 两边不能使用 Int 和 Int 写代码时
  • c++ socket、 listen、accept、recv 、send、 connect函数记录

    文章目录 socket bind 和connect 函数 listen 和accept 函数 send recv read 和write 函数 TCP客户端 Tcp服务端 socket int socket int domain int t