accept函数的参数不是随便填的

2024-06-18 13:08

本文主要是介绍accept函数的参数不是随便填的,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

#include<sys/socket.h>
int accept(int sockfd, struct sockaddr* addr, socklen_t* len)
返回:非负描述字——成功, -1——失败

accept默认会阻塞进程,直到有一个客户连接建立后返回,它返回的是一个新可用的套接字,这个套接字是连接套接字。此时我们需要区分两种套接字,一种套接字正如accept的参数sockfd,它是监听套接字,在调用listen函数之后,一个套接字会从主动连接的套接字变身为一个监听套接字;而accept返回是一个连接套接字,它代表着一个网络已经存在的点点连接。自然要问的是:为什么要有两种套接字?原因很简单,如果使用一个描述字的话,那么它的功能太多,使得使用很不直观,同时在内核确实产生了一个这样的新的描述字。

如果accept成功返回,则服务器与客户已经正确建立连接了,此时服务器通过accept返回的套接字来完成与客户的通信。

参数sockfd

参数sockfd就是上面解释中的监听套接字,这个套接字用来监听一个端口,当有一个客户与服务器连接时,它使用这个一个端口号,而此时这个端口号正与这个 套接字关联。当然客户不知道套接字这些细节,它只知道一个地址和一个端口号。

参数addr

这是一个结果参数,它用来接受一个返回值,这返回值指定客户端的地址,当然这个地址是通过某个地址结构来描述的,用户应该知道这一个什么样的地址结 构。如果对客户的地址不感兴趣,那么可以把这个值设置为NULL。

参数len

如同大家所认为的,它也是结果的参数,用来接受上述addr的结构的大小的,它指明addr结构所占有的字节个数。同样的,它也可以被设置为NULL。

但是,如果你给accept函数第2和第3个参数赋值后,就要记得“用之”,否则就会报错。

举个简单的例子

客户端程序都相同,如下:

#include <stdio.h>
#include <string.h>//memset strlen
#include <stdlib.h>#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>#include <ctime>
#include <arpa/inet.h>/*
unistd.h 中所定义的接口通常都是大量针对系统调用的封装(英语:wrapper functions)
如 fork、pipe 以及各种 I/O 原语(read、write、close 等等)
*/
#include <unistd.h>#include <wait.h>#define MAX_STR 256
int main(){char buf[MAX_STR];char succ[]="success";char fail[]="failed";int clientFd;clientFd=socket(AF_INET,SOCK_STREAM,0);//0:按给定的域和套接字类型选择默认协议struct sockaddr_in serverAddr;memset(&serverAddr,0,sizeof(serverAddr));serverAddr.sin_family=AF_INET;serverAddr.sin_port=htons(12345);serverAddr.sin_addr.s_addr=inet_addr("127.0.0.1");printf("Socket has been created.\n");int cRes=connect(clientFd,(struct sockaddr*)&serverAddr,sizeof(serverAddr));//判断是否成功if(cRes<0){printf("fail to connect\n");exit(1);}else{printf("connect success!\n");}int recvLen=recv(clientFd,(void*)buf,MAX_STR,0);if(recvLen>0){printf("recv success:\n");printf("recv: %s\n",buf);send(clientFd,(void*)succ,strlen(succ),0);//不接受带外数据,阻塞式,可将数据路由出本地网络}else{printf("fail to recv the server's data\n");send(clientFd,(void*)fail,strlen(fail),0);}close(clientFd);printf("Now the connection has been broken\n");close(clientFd);return 0;
}


服务端1:
acceptFd = accept(serverFd,(struct sockaddr*)&clientAddr,(socklen_t*)&clientLen);

后续程序中使用到了clientAddr,clinetLen,程序没有问题

#include <stdio.h>
#include <string.h>//memset strlen
#include <stdlib.h>#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>#include <ctime>
#include <arpa/inet.h>/*
unistd.h 中所定义的接口通常都是大量针对系统调用的封装(英语:wrapper functions)
如 fork、pipe 以及各种 I/O 原语(read、write、close 等等)
*/
#include <unistd.h>#include <wait.h>#define MAX_STR 256
int count=0;
int main(){char buf[MAX_STR];char sayHello[]="Good morning Mr S!";int serverFd;serverFd=socket(AF_INET,SOCK_STREAM,0);int acceptFd;	struct sockaddr_in clientAddr;int clientLen;struct sockaddr_in serverAddr;memset(&serverAddr,0,sizeof(serverAddr));serverAddr.sin_family=AF_INET;serverAddr.sin_port= htons(12345);serverAddr.sin_addr.s_addr=htonl(INADDR_ANY);bind(serverFd,(sockaddr*)&serverAddr,sizeof(serverAddr));printf("Socket has been created and bind\n");listen(serverFd,5);while(true){printf("--------------------------%d\n",count++);printf("Now listening...\n");/* 接受客户端申请的连接 */acceptFd = accept(serverFd,(struct sockaddr*)&clientAddr,(socklen_t*)&clientLen);/* 如果client成功连接到server, 则执行 */if(acceptFd >= 0){printf("Now the link has been connected.\n");/* 从客户端的套接字中提取出IP地址 和其他信息*/int clientip = clientAddr.sin_addr.s_addr;printf("Client ip : %d.%d.%d.%d\n",clientip&255,(clientip>>8)&255,(clientip>>16)&255,(clientip>>24)&255);printf("Client prot : %d\n",ntohs(clientAddr.sin_port));/* 使用send向client发送信息 */sprintf(buf,"THE SEND MSG");printf("[SEND] Starting sending [send] msg ...\n");send(acceptFd, (void*)buf, strlen(buf),0);//发送数据 strlen(buff) bytes数据recv(acceptFd, (void*)buf, MAX_STR, 0 );//接收客户端反馈,成功或失败?//MAXN_STR:最大努力接收if(strlen(buf) > 0)printf("[SUCC] Sending succeed.\n");elseprintf("[FAIL] Sending failed.\n");/* 关闭此连接 */close(acceptFd);printf("Disconnect the link.\n");}else{/*  与client连接失败 */printf("ERROR: Failed while establish the link!\n");}}close(serverFd);return 0;
}


服务端程序2:
acceptFd = accept(serverFd,NULL,NULL);
也没有问题

#include <stdio.h>
#include <string.h>//memset strlen
#include <stdlib.h>#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>#include <ctime>
#include <arpa/inet.h>/*
unistd.h 中所定义的接口通常都是大量针对系统调用的封装(英语:wrapper functions)
如 fork、pipe 以及各种 I/O 原语(read、write、close 等等)
*/
#include <unistd.h>#include <wait.h>#define MAX_STR 256
int count=0;
int main(){char buf[MAX_STR];char sayHello[]="Good morning Mr S!";int serverFd;serverFd=socket(AF_INET,SOCK_STREAM,0);int acceptFd;	struct sockaddr_in clientAddr;int clientLen;struct sockaddr_in serverAddr;memset(&serverAddr,0,sizeof(serverAddr));serverAddr.sin_family=AF_INET;serverAddr.sin_port= htons(12345);serverAddr.sin_addr.s_addr=htonl(INADDR_ANY);bind(serverFd,(sockaddr*)&serverAddr,sizeof(serverAddr));printf("Socket has been created and bind\n");listen(serverFd,5);while(true){printf("--------------------------%d\n",count++);printf("Now listening...\n");/* 接受客户端申请的连接 */acceptFd = accept(serverFd,NULL,NULL);/* 如果client成功连接到server, 则执行 */if(acceptFd >= 0){printf("Now the link has been connected.\n");/* 从客户端的套接字中提取出IP地址 和其他信息int clientip = clientAddr.sin_addr.s_addr;printf("Client ip : %d.%d.%d.%d\n",clientip&255,(clientip>>8)&255,(clientip>>16)&255,(clientip>>24)&255);printf("Client prot : %d\n",ntohs(clientAddr.sin_port));*//* 使用send向client发送信息 */sprintf(buf,"THE SEND MSG");printf("[SEND] Starting sending [send] msg ...\n");send(acceptFd, (void*)buf, strlen(buf),0);//发送数据 strlen(buff) bytes数据recv(acceptFd, (void*)buf, MAX_STR, 0 );//接收客户端反馈,成功或失败?//MAXN_STR:最大努力接收if(strlen(buf) > 0)printf("[SUCC] Sending succeed.\n");elseprintf("[FAIL] Sending failed.\n");/* 关闭此连接 */close(acceptFd);printf("Disconnect the link.\n");}else{/*  与client连接失败 */printf("ERROR: Failed while establish the link!\n");}}close(serverFd);return 0;
}
但是,如果你使用了
acceptFd = accept(serverFd,(struct sockaddr*)&clientAddr,(socklen_t*)&clientLen);
却没有用之,程序就会报错!可以自己试下如下程序,具体原因不知道,但是恶心是恶心够了。。。
#include <stdio.h>
#include <string.h>//memset strlen
#include <stdlib.h>#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>#include <ctime>
#include <arpa/inet.h>/*
unistd.h 中所定义的接口通常都是大量针对系统调用的封装(英语:wrapper functions)
如 fork、pipe 以及各种 I/O 原语(read、write、close 等等)
*/
#include <unistd.h>#include <wait.h>#define MAX_STR 256
int count=0;
int main(){char buf[MAX_STR];char sayHello[]="Good morning Mr S!";int serverFd;serverFd=socket(AF_INET,SOCK_STREAM,0);int acceptFd;	struct sockaddr_in clientAddr;int clientLen;struct sockaddr_in serverAddr;memset(&serverAddr,0,sizeof(serverAddr));serverAddr.sin_family=AF_INET;serverAddr.sin_port= htons(12345);serverAddr.sin_addr.s_addr=htonl(INADDR_ANY);bind(serverFd,(sockaddr*)&serverAddr,sizeof(serverAddr));printf("Socket has been created and bind\n");listen(serverFd,5);while(true){printf("--------------------------%d\n",count++);printf("Now listening...\n");/* 接受客户端申请的连接 */acceptFd = accept(serverFd,(struct sockaddr*)&clientAddr,(socklen_t*)&clientLen);/* 如果client成功连接到server, 则执行 */if(acceptFd >= 0){printf("Now the link has been connected.\n");/* 从客户端的套接字中提取出IP地址 和其他信息int clientip = clientAddr.sin_addr.s_addr;printf("Client ip : %d.%d.%d.%d\n",clientip&255,(clientip>>8)&255,(clientip>>16)&255,(clientip>>24)&255);printf("Client prot : %d\n",ntohs(clientAddr.sin_port));*//* 使用send向client发送信息 */sprintf(buf,"THE SEND MSG");printf("[SEND] Starting sending [send] msg ...\n");send(acceptFd, (void*)buf, strlen(buf),0);//发送数据 strlen(buff) bytes数据recv(acceptFd, (void*)buf, MAX_STR, 0 );//接收客户端反馈,成功或失败?//MAXN_STR:最大努力接收if(strlen(buf) > 0)printf("[SUCC] Sending succeed.\n");elseprintf("[FAIL] Sending failed.\n");/* 关闭此连接 */close(acceptFd);printf("Disconnect the link.\n");}else{/*  与client连接失败 */printf("ERROR: Failed while establish the link!\n");}}close(serverFd);return 0;
}


这篇关于accept函数的参数不是随便填的的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1072077

相关文章

SpringBoot请求参数接收控制指南分享

《SpringBoot请求参数接收控制指南分享》:本文主要介绍SpringBoot请求参数接收控制指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring Boot 请求参数接收控制指南1. 概述2. 有注解时参数接收方式对比3. 无注解时接收参数默认位置

Python的time模块一些常用功能(各种与时间相关的函数)

《Python的time模块一些常用功能(各种与时间相关的函数)》Python的time模块提供了各种与时间相关的函数,包括获取当前时间、处理时间间隔、执行时间测量等,:本文主要介绍Python的... 目录1. 获取当前时间2. 时间格式化3. 延时执行4. 时间戳运算5. 计算代码执行时间6. 转换为指

Python正则表达式语法及re模块中的常用函数详解

《Python正则表达式语法及re模块中的常用函数详解》这篇文章主要给大家介绍了关于Python正则表达式语法及re模块中常用函数的相关资料,正则表达式是一种强大的字符串处理工具,可以用于匹配、切分、... 目录概念、作用和步骤语法re模块中的常用函数总结 概念、作用和步骤概念: 本身也是一个字符串,其中

Python使用getopt处理命令行参数示例解析(最佳实践)

《Python使用getopt处理命令行参数示例解析(最佳实践)》getopt模块是Python标准库中一个简单但强大的命令行参数处理工具,它特别适合那些需要快速实现基本命令行参数解析的场景,或者需要... 目录为什么需要处理命令行参数?getopt模块基础实际应用示例与其他参数处理方式的比较常见问http

Linux内核参数配置与验证详细指南

《Linux内核参数配置与验证详细指南》在Linux系统运维和性能优化中,内核参数(sysctl)的配置至关重要,本文主要来聊聊如何配置与验证这些Linux内核参数,希望对大家有一定的帮助... 目录1. 引言2. 内核参数的作用3. 如何设置内核参数3.1 临时设置(重启失效)3.2 永久设置(重启仍生效

SpringMVC获取请求参数的方法

《SpringMVC获取请求参数的方法》:本文主要介绍SpringMVC获取请求参数的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下... 目录1、通过ServletAPI获取2、通过控制器方法的形参获取请求参数3、@RequestParam4、@

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

MySQL中FIND_IN_SET函数与INSTR函数用法解析

《MySQL中FIND_IN_SET函数与INSTR函数用法解析》:本文主要介绍MySQL中FIND_IN_SET函数与INSTR函数用法解析,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一... 目录一、功能定义与语法1、FIND_IN_SET函数2、INSTR函数二、本质区别对比三、实际场景案例分

Spring Boot项目部署命令java -jar的各种参数及作用详解

《SpringBoot项目部署命令java-jar的各种参数及作用详解》:本文主要介绍SpringBoot项目部署命令java-jar的各种参数及作用的相关资料,包括设置内存大小、垃圾回收... 目录前言一、基础命令结构二、常见的 Java 命令参数1. 设置内存大小2. 配置垃圾回收器3. 配置线程栈大小