mfc socket onreceive函数不被调用_Linux socket网络编程系统调用「DaemonCoder」

ebdf1a9a99feebb47ea2031fdd5472c4.png

创建socket

linux在 sys/socket.h 下定义了 socket() 系统调用,来创建一个socket,返回一个文件描述符,读写文件的函数也可以用来操作socket。

f1e9469d9fbfbe23402ddd810a6607d6.png
  • domain参数

在之前 Linux socket地址结构体 文章中介绍了三种协议族,domain参数用来指定用哪种协议族,常见的是 PF_INET(IPv4)、PF_INET6(IPv6) 和 PF_UNIX(Unix本地域)。

  • type参数

type参数指定服务类型,常见的是SOCK_STREAM(流服务)、SOCK_DGRAM(数据报)、SOCK_RAW(原始套接字)。对于TCP/IP协议族,需要指定type为 SOCK_STREAM,如果想使用UDP协议则用 SOCK_DGRAM。SOCK_RAW 除了可以处理普通的网络报文之外,可以用来处理前面所述无法处理的报文,如ICMP、IGMP等,可以由用户构造IP头,总体来说,SOCK_RAW 可以处理一些特殊协议报文以及操作IP层及其以上的数据。

  • protocal参数

protocal参数表示在前面两个参数筛选出的协议集合中,再指定一个具体的协议,传入0表示使用默认协议。通常前两个参数就可以确定一个要使用的协议了,一般这个参数传0就可以。

  • 返回

socket()返回一个文件描述符,对socket操作的其他函数,往往需要传入这个值来指定要操作的是哪个socket。socket()调用失败返回-1,并设置errno。用户可以 #include ,然后使用errno变量。

命名socket

通常,网络编程中服务器端程序要绑定一个socket地址,如tcp上的80端口,来提供给客户端连接。给socket绑定地址叫做命名socket,不命名socket表示采用操作系统自动分配的地址。服务器端通常需要命名socket,客户端一般不需要。

linux提供的命名socket的系统调用为:

e70b670208a8d11be1ec1b31d9813a70.png
  • sockfd参数

前面所述socket()返回的文件描述符。

  • addr参数

指定要绑定的socket地址,sockaddr类型的指针,可以由sockaddr_in、sockaddr_in6、sockaddr_un等类型强转过来,详见 Linux socket地址结构体。

  • addrlen参数

上述addr参数所指结构的大小。

  • 返回

成功时返回0,失败返回-1并设置errno。bind()常见的errno值为 EACCES 和 EADDRINUSE。EACCES表示当前用户没有权限绑定的地址,如端口0~1023。EADDRINUSE表示当前地址已经被占用。

监听socket

命名socket之后,还不能马上接收连接,需要创建一个队列,以便客户端连接较多时,存储待处理的连接。如果队列被占满,后续再在客户端连接,会收到 ECONNREFUSED 错误,即连接被拒绝。

linux提供了listen系统调来创建这个队列:

c42359b0d789cedec6e597a7080d39a5.png
  • sockfd参数

前面所述socket()返回的文件描述符。

  • backlog参数

指定队列的大小。

  • 返回

成功时返回0,失败返回-1并设置errno。

接受连接

linux提供了accept系统调用来接受连接:

e398d877a19146f4ae8059afbd9cfd0c.png
  • sockfd参数

前面所述socket()返回的文件描述符。

  • addr参数

接受客户端连接的socket地址。

  • addrlen参数

上述addr参数所指结构的大小。

  • 返回

失败返回-1并设置errno。成功时,返回一个新的文件描述符,对应接受的客户端连接,后续与客户端通信时读写此文件描述符即可。

读写数据

文件读写的函数同样可以用来读写socket,但是系统还提供了专门用于socket数据读写的函数:

34841a13ec6e216015995fa55626b278.png

发起连接

connect函数用于客户端发起连接。

32eae2c784608d739edf276dae0a575a.png

成功返回0,失败返回-1并设置errno。常见的errno为 ECONNREFUSED 和 ETIMEDOUT,分别表示服务端拒绝连接、连接超时。

关闭连接

关闭文件的函数可以用来关闭socket连接,如close()函数:

6de4f4ff07f45a02cd639ef6e64598fb.png

当在多进程编程中,一个进程fork之后得到的父子进程都可以操作原来的socket,这种情况下fork时会把原来父进程中打开的socket的引用记数加1,无论是在父进程还是子进程中,调用close()时只是把socket的引用记数减1,减到0时才会真正地关闭连接。如果想要立即关闭连接,而不是减引用记数的话,可以用专门针对网络编程的shutdown()函数:

7716c3e435581b55fd2a2aa3b7616934.png

howto参数提供了三种关闭方式:

  • SHUT_RD:关闭sockfd上的读,应用程序不能再执行读操作,并且socket接收缓冲区中的数据都被丢弃。
  • SHUT_WR:关闭写,应用程序不能再执行写操作,但是发送缓冲区中的数据会在真正关闭连接之前全部发送出去。
  • SHUT_RDWR:同时关闭读写。

shutdown()成功时返回0,失败返回-1并设置errno。

服务器端示例

17d7b89ee17d194c54ca78e1f8dbc054.png
be6bd835bea409d01c01b376fee0a050.png

客户端端示例

f61c4367def1324c52eb724bc45267c6.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值