lwIP TCP/IP 协议栈笔记之十八: Socket接口编程

目录

1. Socket 概述

2. LwIP 中的socket

3. Socket API

3.1 socket()

3.2 bind()

3.3 connect()

3.4 listen()

3.5 accept()

3.6 read()、recv()、recvfrom()

3.7 sendto()

3.8 send()

3.9 write()

3.10 close()

3.11 ioctl()、ioctlsocket()

3.12 setsockopt()

3.13 getsockopt()

4. 实验例程

4.1  TCP Server

4.2  TCP Client


1. Socket 概述

Socket 英文原意是“孔”或者“插座”的意思,在网络编程中,通常将其称之为“套接字”,当前网络中的主流程序设计都是使用Socket 进行编程的,因为它简单易用,更是一个标准,能在不同平台很方便移植。

套接字(socket)是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信。网络套接字是IP地址与端口的组合。

总之,套接字Socket=(IP地址:端口号),套接字的表示方法是点分十进制的IP地址后面写上端口号,中间用冒号或逗号隔开。每一个传输层连接唯一地被通信两端的两个端点(即两个套接字)所确定。

Socket最初是加利福尼亚大学Berkeley分校为Unix系统开发的网络通信接口。后来随着TCP/IP网络的发展,Socket成为最为通用的应用程序接口,也是在Internet上进行应用开发最为通用的API

为了能让更多开发者直接上手LwIP 的编程,专门设计了LwIP 的第三种编程接口——Socket API,它兼容BSD Socket。

Socket 虽然是能在多平台移植,但是LwIP 中的Socket 并不完善,因为LwIP 设计之初就是为了在嵌入式平台中使用,它只实现了完整Socket 的部分功能,不过,在嵌入式平台中,这些功能早已足够。

2. LwIP 中的socket

在LwIP 中,Socket API 是基于NETCONN API 之上来实现的,系统最多提供MEMP_NUM_NETCONN 个netconn 连接结构,因此决定Socket 套接字的个数也是那么多个。

为了更好对netconn 进行封装,LwIP 还定义了一个套接字结构体——lwip_sock(称之为Socket 连接结构),每个lwip_sock 内部都有一个netconn 的指针,实现了对netconn 的再次封装。

LwIP 定义了一个lwip_sock 类型的sockets数组,通过套接字就可以直接索引并且访问这个结构体了,这也是为什么套接字是一个整数的原因,lwip_sock 结构体是比较简单的,因为基本上全是依赖netconn 实现。

#define NUM_SOCKETS MEMP_NUM_NETCONN    // 默认是4

/** 全局可用套接字数组 **/
static struct lwip_sock sockets[NUM_SOCKETS];

union lwip_sock_lastdata {
  struct netbuf *netbuf;
  struct pbuf *pbuf;
};

/** 包含用于套接字的所有内部指针和状态*/
struct lwip_sock {
  /** 套接字当前是在netconn 上构建的,每个套接字都有一个netconn*/
  struct netconn *conn;
  /** 从上一次读取中留下的数据 */
  union lwip_sock_lastdata lastdata;
#if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
  /** number of times data was received, set by event_callback(),
      tested by the receive and select functions */
  s16_t rcvevent;
  /** number of times data was ACKed (free send buffer), set by event_callback(),
      tested by select */
  u16_t sendevent;
  /** error happened for this socket, set by event_callback(), tested by select */
  u16_t errevent;
  /** 使用select 等待此套接字的线程数 */
  SELWAIT_T select_waiting;
#endif /* LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL */
#if LWIP_NETCONN_FULLDUPLEX
  /* counter of how many threads are using a struct lwip_sock (not the 'int') */
  u8_t fd_used;
  /* status of pending close/delete actions */
  u8_t fd_free_pending;
#define LWIP_SOCK_FD_FREE_TCP  1
#define LWIP_SOCK_FD_FREE_FREE 2
#endif
};

3. Socket API

3.1 socket()

向内核申请一个套接字,在本质上该函数其实就是对netconn_new()函数进行了封装,虽然说不是直接调用它,但是主体完成的工作就做了 netconn_new()函数的事情,而且该函数本质是一个宏定义.

/** @ingroup socket */
#define socket(domain,type,protocol)              lwip_socket(domain,type,protocol)

int
lwip_socket(int domain, int type, int protocol);

#define AF_INET         2

/* Socket protocol types (TCP/UDP/RAW) */
#define SOCK_STREAM     1
#define SOCK_DGRAM      2
#define SOCK_RAW        3

参数domain :表示该套接字使用的协议簇,对于TCP/IP 协议来说,该值始终为AF_INET。

参数type: 指定了套接字使用的服务类型,可能的类型有3 种:

1. SOCK_STREAM:提供可靠的(即能保证数据正确传送到对方)面向连接的Socket 服务,多用于资料(如文件)传输,如TCP 协议。

2. SOCK_DGRAM:是提供无保障的面向消息的Socket 服务,主要用于在网络上

  • 14
    点赞
  • 94
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值