文章目录

  • 前言
  • 函数描述
  • 代码实例
  • 如何得到客户端的IP 和 端口号
前言

当使用tcp服务器使用socket创建通信文件描述符,bind绑定了文件描述符,服务器ip和端口号,listen将服务器端的主动描述符转为被动描述符进行监听之后,接口accept通过三次握手与客户端建立连接

TCP 编程模型如下:


函数描述
  • #include <sys/socket.h>
  • int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
  • 函数功能:
    被动监听客户端发起的tcp连接请求,三次握手后连接建立成功。客户端connect函数请求发起连接。
    连接成功后服务器的tcp协议会记录客端的ip和端口,如果是跨网通信,记录ip的就是客户端所在路由器的公网ip
  • 返回值:
    成功:返回一个通信描述符,专门用于与连接成功的客户端进行通信。
    失败:返回-1 ,并设置errno
  • 函数参数:
    a. sockfd 已经被listen转为了被动描述符的“套接字文件描述符”,专门用于客户端的监听,入股sockfs没有被listen函数转为被动描述符,则accept是无法将其用来监听客户端连接的。
    套接字文件描述符默认是阻塞的,即如果没有客户端请求连接的时候,此时accept会阻塞,直到有客户端连接;如果不想套接字文件描述符阻塞,则可以创建套接字 socket函数 时指定typeSOCK_NOBLOCK
    b. addrlen表示第二个参数addr的大小,不顾要求给定地址
    c. addr: 用于记录发起连接请求的那个客户端的IP端口
    建立连接时服务器的TCP协议会自动解析客户端发来的数据包,从中获取客户端的IP和端口号
    这里如果服务器应用层需要用到客户端的 IP和端口号,可以给accept指定第二个参数addr,以获取TCP链接时的客户端ip和端口号;如果服务器应用层不需要,则写NULL即可
    addr的结构体类型为 struct sockaddr,在listen函数详解中我们有介绍过,由于这个结构体用起来不是非常方便,我们需要定义struct sockaddr_in结构体来使得sockaddr结构体操作更为便捷。具体使用如下:

    struct sockaddr_in naddr = {0};int nsize = sizeof(naddr);
    int cfd = accept(sockfd, (struct sockaddr *)&naddr, &nsize);
    
代码实例
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>void print_err(char *str, int line, int err_no) {printf("%d, %s :%s\n",line,str,strerror(err_no));_exit(-1);
}int main()
{int skfd = -1, ret = -1;skfd = socket(AF_INET, SOCK_STREAM, 0);if ( -1 == skfd) {print_err("socket failed",__LINE__,errno);}struct sockaddr_in addr;addr.sin_family = AF_INET; //设置tcp协议族addr.sin_port = 6789; //设置端口号addr.sin_addr.s_addr = inet_addr("192.168.102.169"); //设置ip地址ret = bind(skfd, (struct sockaddr*)&addr, sizeof(addr));if ( -1 == ret) {print_err("bind failed",__LINE__,errno);}/*将套接字文件描述符从主动转为被动文件描述符,然后用于被动监听客户端的连接*/ret = listen(skfd, 3);if ( -1 == ret ) {print_err("listen failed", __LINE__, errno);}/*被动监听客户端发起的tcp连接请求,三次握手后连接建立成功*/int cfd = -1;struct sockaddr_in caddr = {0}; //为应用层获取客户端的IP和端口号int csize = 0;cfd = accept(skfd, (struct sockaddr*)&caddr, &csize);if (-1 == cfd) {print_err("accept failed", __LINE__, errno);}return 0;
}
如何得到客户端的IP 和 端口号

比如程序中想要打印客户端的ip和端口号,这里就需要使用到ntohsinet_ntoa函数进行端序转换,因为客户端的端口和ip是服务器的TCP协议,从客户端发送端网络数据包中提取出来,网络数据包的端序属于网络端序,主机接收到数据后如果想要使用的话,就必须从网络端序转为主机端序。

举例如下:

struct sockaddr_in caddr = {0};int csize = sizeof(caddr);
cfd = accept(sockfd, (struct sockaddr *)&caddr, &csize);printf("cport = %d, caddr = %s\n", ntohs(caddr.sin_port),inet_ntoa(caddr.sin_addr));

C语言网络编程:accept函数详解相关推荐

  1. linux网络编程常用函数详解与实例(socket--bind--listen--accept)

    常用的网络命令: netstat 命令netstat是用来显示网络的连接,路由表和接口统计等网络的信息.netstat有许多的选项我们常用的选项是 -an 用来显示详细的网络状态.至于其它的选项我们可 ...

  2. linux socket编程 accept函数详解

    int accept(int sockfd,struct sockaddr * addr,socklen_t * addrlen); sockfd的参数为listen()函数返回的监听套接字: add ...

  3. tcp/ip网络编程--accept()函数返回的套接字

    tcp/ip网络编程–accept()函数返回的套接字 套接字:1)套接字是对网络中不同主机的应用进程之间进行双向通信的端点的抽象:一个套接字就是网络进程通信的一端.[1] 2)套接字是用来与另一个进 ...

  4. gets和fgets函数及其区别,C语言gets和fgets函数详解

    gets和fgets函数及其区别,C语言gets和fgets函数详解 每当讨论 gets 函数时,大家不由自主地就会想起 1988 年的"互联网蠕虫",它在 UNIX 操作系统的 ...

  5. puts和fputs函数及其区别,C语言puts和fputs函数详解

    puts和fputs函数及其区别,C语言puts和fputs函数详解 与 gets 函数一样,对于 puts 函数,同样建议使用 fputs 函数来代替 puts 函数.如下面的示例代码所示: int ...

  6. Visual C++网络编程经典案例详解 第9章 实用播放器 数据读取与播放控制 识别数据文件信息

    识别数据文件信息主要是指对mp3数据格式识别 定义顺序代码如下 typedef struct mp3_struct //自定义mp3结构体 {char heade[3]; //tag字符标记char ...

  7. C语言strcpy、strcnpy函数详解

    C语言strcpy.strcnpy函数详解 一.strcpy函数 1.函数原型 2.参数.返回值解析 3.注意事项 4.strcpy函数模拟实现 二.strncpy函数 1.函数原型 2.与strcp ...

  8. java的匿名函数_JAVA语言中的匿名函数详解

    本文主要向大家介绍了JAVA语言中的匿名函数详解,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助. 一.使用匿名内部类 匿名内部类由于没有名字,所以它的创建方式有点儿奇怪.创建格式如下: ...

  9. C语言strcat、strncat函数详解

    C语言strcat.strncat函数详解 一.strcat函数 1.函数原型 2.函数参数.返回值解析 3.函数作用 4.注意事项 5.strcat函数模拟实现 二.strncat函数 1.函数原型 ...

最新文章

  1. 笑了,面试官问我知不知道异步编程的Future。
  2. mysql变量使用总结
  3. anaconda不同虚拟环境下使用jupyter的问题
  4. php父子遍历,php无限分类父子追溯方法
  5. 亲测使用 swagger 动态修改后台默认访问地址 swagger-ui.html
  6. 通用usb驱动libusb介绍和使用示例
  7. ajax跨域获取数据后处理,简单实现ajax获取跨域数据
  8. Ubutun16.04安装和使用daemontools
  9. CDN 网站部署全站加速服务
  10. L2 Spare the spider 不要伤害蜘蛛
  11. word 多级编号列表
  12. 调和级数相关极限合集
  13. 防火墙工作在哪个层_数据库安全关键技术之数据库防火墙技术
  14. 查询活动开始时间和结束时间
  15. centos如何在官网下载以前的版本
  16. 自然语言处理中的Character Embedding技术
  17. Linux(ubuntu)中删除除了一个文件之外的所有文件
  18. 计算机网络原理课后作业答案,自考04741《计算机网络原理》课后习题答案
  19. 椭圆机的正确使用方法,你学会了吗?
  20. 【数据挖掘算法分享】机器学习平台——回归算法之随机森林

热门文章

  1. WebGoat教程学习(三)--Ajax安全
  2. firefox+linux+nginx搭建server与client通过证书双向认证环境
  3. usaco Arithmetic Progressions(看了题解)
  4. 经典dp最长递增子序列
  5. arcgis xml 下载 切片_vue/cli3整合Cesium,加载离线arcgis 切片
  6. 编码 data:text/html;c,关于 Data URI Scheme -- data:image/jpg;base64
  7. 虚拟服务器磁盘满了咋办,虚拟主机磁盘空间不够用怎么办?
  8. html控件无法使用的属性值,用 Enabled 和 disabled 属性禁用 HTML 控件后,取值结果...
  9. mysql内连接运算量会增加多少_新年手打,40道经典MYSQL面试干货,速来收藏
  10. java super快速生成_为什么当我使用编辑器代码生成器时,eclipse会在构造函数中自动添加一个java super()方法?...