
数据包结构定义

包结构定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #define XNET_CFG_PACKET_MAX_SIZE 1516
typedef struct _xnet_packet_t{
uint16_t size;
uint8_t * data;
uint8_t payload[XNET_CFG_PACKET_MAX_SIZE];
}xnet_packet_t;
xnet_packet_t * xnet_alloc_for_send(uint16_t data_size);
xnet_packet_t * xnet_alloc_for_read(uint16_t data_size);
|
实现包发送和读取函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| static xnet_packet_t tx_packet, rx_packet;
xnet_packet_t * xnet_alloc_for_send(uint16_t data_size) {
tx_packet.data = tx_packet.payload + XNET_CFG_PACKET_MAX_SIZE - data_size;
tx_packet.size = data_size;
return &tx_packet;
}
xnet_packet_t * xnet_alloc_for_read(uint16_t data_size) {
rx_packet.data = rx_packet.payload;
rx_packet.size = data_size;
return &rx_packet;
}
|
对包的一些操作函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| #define min(a, b) ((a) > (b) ? (b) : (a))
static void add_header(xnet_packet_t *packet, uint16_t header_size) {
packet->data -= header_size;
packet->size += header_size;
}
static void remove_header(xnet_packet_t *packet, uint16_t header_size) {
packet->data += header_size;
packet->size -= header_size;
}
static void truncate_packet(xnet_packet_t *packet, uint16_t size) {
packet->size = min(packet->size, size);
}
|
总代码
app.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include <stdio.h>
#include "xnet_tiny.h"
int main (void) {
xnet_init();
printf("xnet running\n");
while (1) {
xnet_poll();
}
return 0;
}
|
xnet_tiny.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| #ifndef XNET_TINY_H
#define XNET_TINY_H
#include <stdint.h>
#define XNET_CFG_PACKET_MAX_SIZE 1516
typedef struct _xnet_packet_t{
uint16_t size;
uint8_t * data;
uint8_t payload[XNET_CFG_PACKET_MAX_SIZE];
}xnet_packet_t;
xnet_packet_t * xnet_alloc_for_send(uint16_t data_size);
xnet_packet_t * xnet_alloc_for_read(uint16_t data_size);
void xnet_init (void);
void xnet_poll(void);
#endif
|
xnet_tiny.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
| #include "xnet_tiny.h"
#define min(a, b) ((a) > (b) ? (b) : (a))
static xnet_packet_t tx_packet, rx_packet;
xnet_packet_t * xnet_alloc_for_send(uint16_t data_size) {
tx_packet.data = tx_packet.payload + XNET_CFG_PACKET_MAX_SIZE - data_size;
tx_packet.size = data_size;
return &tx_packet;
}
xnet_packet_t * xnet_alloc_for_read(uint16_t data_size) {
rx_packet.data = rx_packet.payload;
rx_packet.size = data_size;
return &rx_packet;
}
static void add_header(xnet_packet_t *packet, uint16_t header_size) {
packet->data -= header_size;
packet->size += header_size;
}
static void remove_header(xnet_packet_t *packet, uint16_t header_size) {
packet->data += header_size;
packet->size -= header_size;
}
static void truncate_packet(xnet_packet_t *packet, uint16_t size) {
packet->size = min(packet->size, size);
}
void xnet_init (void) {
}
void xnet_poll(void) {
}
|
以太网协议
以太网封装驱动
定义驱动的函数
1 2 3 4 5
| xnet_err_t xnet_driver_open (uint8_t * mac_addr);
xnet_err_t xnet_driver_send (xnet_packet_t * packet);
xnet_err_t xnet_driver_read (xnet_packet_t ** packet);
|
实现驱动的函数
port_pcap.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
| #include <string.h>
#include <stdlib.h>
#include "pcap_device.h"
#include "xnet_tiny.h"
static pcap_t * pcap;
const char * ip_str = "192.168.254.1";
const char my_mac_addr[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
xnet_err_t xnet_driver_open (uint8_t * mac_addr) {
memcpy(mac_addr, my_mac_addr, sizeof(my_mac_addr));
pcap = pcap_device_open(ip_str, mac_addr, 1);
if (pcap == (pcap_t *)0) {
exit(-1);
}
return XNET_ERR_OK;
}
xnet_err_t xnet_driver_send (xnet_packet_t * packet) {
return pcap_device_send(pcap, packet->data, packet->size);
}
xnet_err_t xnet_driver_read (xnet_packet_t ** packet) {
uint16_t size;
xnet_packet_t * r_packet = xnet_alloc_for_read(XNET_CFG_PACKET_MAX_SIZE);
size = pcap_device_read(pcap, r_packet->data, XNET_CFG_PACKET_MAX_SIZE);
if (size) {
r_packet->size = size;
*packet = r_packet;
return XNET_ERR_OK;
}
return XNET_ERR_IO;
}
|
定义枚举_xnet_err_t
1 2 3 4 5 6 7
| typedef enum _xnet_err_t {
XNET_ERR_OK = 0,
XNET_ERR_IO = -1,
}xnet_err_t;
|
以太网输入输出处理
以太网初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
static xnet_err_t ethernet_init (void) {
xnet_err_t err = xnet_driver_open(netif_mac);
if (err < 0) return err;
return XNET_ERR_OK;
}
|
以太网数据帧格式

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| #pragma pack(1)
#define XNET_IPV4_ADDR_SIZE 4
#define XNET_MAC_ADDR_SIZE 6
typedef struct _xether_hdr_t {
uint8_t dest[XNET_MAC_ADDR_SIZE];
uint8_t src[XNET_MAC_ADDR_SIZE];
uint16_t protocol;
}xether_hdr_t;
#pragma pack()
|
发送和接收以太网帧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| static uint8_t netif_mac[XNET_MAC_ADDR_SIZE];
#define swap_order16(v) ((((v) & 0xFF) << 8) | (((v) >> 8) & 0xFF))
static xnet_err_t ethernet_out_to(xnet_protocol_t protocol, const uint8_t *mac_addr, xnet_packet_t * packet) {
xether_hdr_t* ether_hdr;
add_header(packet, sizeof(xether_hdr_t));
ether_hdr = (xether_hdr_t*)packet->data;
memcpy(ether_hdr->dest, mac_addr, XNET_MAC_ADDR_SIZE);
memcpy(ether_hdr->src, netif_mac, XNET_MAC_ADDR_SIZE);
ether_hdr->protocol = swap_order16(protocol);
return xnet_driver_send(packet);
}
static void ethernet_in (xnet_packet_t * packet) {
if (packet->size <= sizeof(xether_hdr_t)) {
return;
}
xether_hdr_t* hdr = (xether_hdr_t*)packet->data;
switch (swap_order16(hdr->protocol)) {
case XNET_PROTOCOL_ARP:
break;
case XNET_PROTOCOL_IP: {
break;
}
}
}
|
定义枚举协议的类型
1 2 3 4 5 6 7
| typedef enum _xnet_protocol_t {
XNET_PROTOCOL_ARP = 0x0806,
XNET_PROTOCOL_IP = 0x0800,
}xnet_protocol_t;
|
轮询处理数据包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
static void ethernet_poll (void) {
xnet_packet_t * packet;
if (xnet_driver_read(&packet) == XNET_ERR_OK) {
ethernet_in(packet);
}
}
void xnet_init (void) {
ethernet_init();
}
void xnet_poll(void) {
ethernet_poll();
}
|
ARP协议
ARP的初始化
Q: 因为以太网包包头需要目的MAC地址, 已知目的IP地址如何获得目的MAC地址?
A: 发送一个广播包Broadcast, 询问目的MAC地址, 目的主机回复MAC地址.
xxxxxxxxxx public static void main(String[] args) { QueueArray queueArray = new QueueArray(3); Scanner scanner = new Scanner(System.in); boolean loop = true; while(loop) { System.out.println(“入队:in, 出队:out, 判空:empty, 判满:full, 查看:check, 退出:exit”); String next = scanner.next(); switch (next) { case “in” : System.out.println(“请输入数据”); queueArray.enter(scanner.nextInt()); break; case “out” : try { System.out.println(“出队数据为: “ + queueArray.leave()); } catch (Exception e) { System.out.println(e.getMessage()); } break; case “empty” : if(queueArray.isEmpty()) { System.out.println(“队列为空”); break; } System.out.println(“队列非空”); break; case “full” : if(queueArray.isFull()) { System.out.println(“队列已满”); break; } System.out.println(“队列未满”); break; case “check” : queueArray.traverse(); break; case “exit” : System.out.println(“已退出”); loop = false; break; } } scanner.close();}java

ARP表


ARP表结构定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| #define XNET_IPV4_ADDR_SIZE 4
#define XNET_MAC_ADDR_SIZE 6
* IP地址
*/
typedef union _xipaddr_t {
uint8_t array[XNET_IPV4_ADDR_SIZE];
uint32_t addr;
}xipaddr_t;
#define XARP_ENTRY_FREE 0
typedef struct _xarp_entry_t {
xipaddr_t ipaddr;
uint8_t macaddr[XNET_MAC_ADDR_SIZE];
uint8_t state;
uint16_t tmo;
uint8_t retry_cnt;
}xarp_entry_t;
|
初始化ARP表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| #define XARP_ENTRY_FREE 0
#define XARP_ENTRY_OK 1
void xarp_init(void) {
arp_entry.state = XARP_ENTRY_FREE;
}
void xnet_init (void) {
ethernet_init();
xarp_init();
}
|
无回报ARP的生成
无回报ARP包

ARP数据包


ARP包结构定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #define XARP_HW_ETHER 0x1
#define XARP_REQUEST 0x1
#define XARP_REPLY 0x2
typedef struct _xarp_packet_t {
uint16_t hw_type, pro_type;
uint8_t hw_len, pro_len;
uint16_t opcode;
uint8_t sender_mac[XNET_MAC_ADDR_SIZE];
uint8_t sender_ip[XNET_IPV4_ADDR_SIZE];
uint8_t target_mac[XNET_MAC_ADDR_SIZE];
uint8_t target_ip[XNET_IPV4_ADDR_SIZE];
}xarp_packet_t;
|
ARP请求函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| static const xipaddr_t netif_ipaddr = XNET_CFG_NETIF_IP;
static const uint8_t ether_broadcast[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static uint8_t netif_mac[XNET_MAC_ADDR_SIZE];
static xnet_packet_t tx_packet, rx_packet;
static xarp_entry_t arp_entry;
typedef enum _xnet_err_t {
XNET_ERR_OK = 0,
XNET_ERR_IO = -1,
}xnet_err_t;
int xarp_make_request(const xipaddr_t * ipaddr);
xnet_err_t xarp_make_request(const xipaddr_t * ipaddr) {
xarp_packet_t* arp_packet;
xnet_packet_t * packet = xnet_alloc_for_send(sizeof(xarp_packet_t));
arp_packet = (xarp_packet_t *)packet->data;
arp_packet->hw_type = swap_order16(XARP_HW_ETHER);
arp_packet->pro_type = swap_order16(XNET_PROTOCOL_IP);
arp_packet->hw_len = XNET_MAC_ADDR_SIZE;
arp_packet->pro_len = XNET_IPV4_ADDR_SIZE;
arp_packet->opcode = swap_order16(XARP_REQUEST);
memcpy(arp_packet->sender_mac, netif_mac, XNET_MAC_ADDR_SIZE);
memcpy(arp_packet->sender_ip, netif_ipaddr.array, XNET_IPV4_ADDR_SIZE);
memset(arp_packet->target_mac, 0, XNET_MAC_ADDR_SIZE);
memcpy(arp_packet->target_ip, ipaddr->array, XNET_IPV4_ADDR_SIZE);
return ethernet_out_to(XNET_PROTOCOL_ARP, ether_broadcast, packet);
}
|
以太网初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| static const xipaddr_t netif_ipaddr = XNET_CFG_NETIF_IP;
static const uint8_t ether_broadcast[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static uint8_t netif_mac[XNET_MAC_ADDR_SIZE];
static xnet_err_t ethernet_init (void) {
xnet_err_t err = xnet_driver_open(netif_mac);
if (err < 0) return err;
return xarp_make_request(&netif_ipaddr);
}
|
ARP输入处理
当收到一个ARP包时, 经如下步骤进行处理:

ARP输入处理函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| #define xipaddr_is_equal_buf(addr, buf) (memcmp((addr)->array, (buf), XNET_IPV4_ADDR_SIZE) == 0)
void xarp_in(xnet_packet_t * packet) {
if (packet->size >= sizeof(xarp_packet_t)) {
xarp_packet_t * arp_packet = (xarp_packet_t *) packet->data;
uint16_t opcode = swap_order16(arp_packet->opcode);
if ((swap_order16(arp_packet->hw_type) != XARP_HW_ETHER) ||
(arp_packet->hw_len != XNET_MAC_ADDR_SIZE) ||
(swap_order16(arp_packet->pro_type) != XNET_PROTOCOL_IP) ||
(arp_packet->pro_len != XNET_IPV4_ADDR_SIZE)
|| ((opcode != XARP_REQUEST) && (opcode != XARP_REPLY))) {
return;
}
if (!xipaddr_is_equal_buf(&netif_ipaddr, arp_packet->target_ip)) {
return;
}
switch (swap_order16(arp_packet->opcode)) {
case XARP_REQUEST:
xarp_make_response(arp_packet);
update_arp_entry(arp_packet->sender_ip, arp_packet->sender_mac);
break;
case XARP_REPLY:
update_arp_entry(arp_packet->sender_ip, arp_packet->sender_mac);
break;
}
}
}
|
在以太网层处理ARP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
xether_hdr_t* hdr = (xether_hdr_t*)packet->data;
switch (swap_order16(hdr->protocol)) {
case XNET_PROTOCOL_ARP:
remove_header(packet, sizeof(xether_hdr_t));
xarp_in(packet);
break;
}
|
ARP响应函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
xnet_err_t xarp_make_response(xarp_packet_t * arp_packet) {
xarp_packet_t* response_packet;
xnet_packet_t * packet = xnet_alloc_for_send(sizeof(xarp_packet_t));
response_packet = (xarp_packet_t *)packet->data;
response_packet->hw_type = swap_order16(XARP_HW_ETHER);
response_packet->pro_type = swap_order16(XNET_PROTOCOL_IP);
response_packet->hw_len = XNET_MAC_ADDR_SIZE;
response_packet->pro_len = XNET_IPV4_ADDR_SIZE;
response_packet->opcode= swap_order16(XARP_REPLY);
memcpy(response_packet->target_mac, arp_packet->sender_mac, XNET_MAC_ADDR_SIZE);
memcpy(response_packet->target_ip, arp_packet->sender_ip, XNET_IPV4_ADDR_SIZE);
memcpy(response_packet->sender_mac, netif_mac, XNET_MAC_ADDR_SIZE);
memcpy(response_packet->sender_ip, netif_ipaddr.array, XNET_IPV4_ADDR_SIZE);
return ethernet_out_to(XNET_PROTOCOL_ARP, ether_broadcast, packet);
}
|
更新ARP表项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #define XARP_ENTRY_FREE 0
#define XARP_ENTRY_OK 1
static void update_arp_entry(uint8_t * src_ip, uint8_t * mac_addr) {
memcpy(arp_entry.ipaddr.array, src_ip, XNET_IPV4_ADDR_SIZE);
memcpy(arp_entry.macaddr, mac_addr, 6);
arp_entry.state = XARP_ENTRY_OK;
|
ARP表定时更新
获得当前时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| typedef uint32_t xnet_time_t;
const xnet_time_t xsys_get_time(void) {
static uint32_t pre = 0;
return (xnet_time_t)(clock() / CLOCKS_PER_SEC);
}
|
检查是否超时
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
|
int xnet_check_tmo(xnet_time_t * time, uint32_t sec) {
xnet_time_t curr = xsys_get_time();
if (sec == 0) {
*time = curr;
return 0;
} else if (curr - *time >= sec) {
*time = curr;
return 1;
}
return 0;
}
void xarp_init(void) {
arp_entry.state = XARP_ENTRY_FREE;
xnet_check_tmo(&arp_timer, 0);
}
|
查询是否超时, 超时则重新请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
| static xnet_time_t arp_timer;
#define XARP_CFG_ENTRY_PENDING_TMO (1)
#define XARP_CFG_MAX_RETRIES 4
#define XARP_ENTRY_FREE 0
#define XARP_ENTRY_OK 1
#define XARP_ENTRY_RESOLVING 2
#define XARP_TIMER_PERIOD 1
#define XARP_CFG_ENTRY_OK_TMO (5)
#define XARP_CFG_ENTRY_PENDING_TMO (1)
#define XARP_CFG_MAX_RETRIES 4
typedef struct _xarp_entry_t {
xipaddr_t ipaddr;
uint8_t macaddr[XNET_MAC_ADDR_SIZE];
uint8_t state;
uint16_t tmo;
uint8_t retry_cnt;
}xarp_entry_t;
void xarp_poll(void) {
if (xnet_check_tmo(&arp_timer, XARP_TIMER_PERIOD)) {
switch (arp_entry.state) {
case XARP_ENTRY_RESOLVING:
if (--arp_entry.tmo == 0) {
if (arp_entry.retry_cnt-- == 0) {
arp_entry.state = XARP_ENTRY_FREE;
} else {
xarp_make_request(&arp_entry.ipaddr);
arp_entry.state = XARP_ENTRY_RESOLVING;
arp_entry.tmo = XARP_CFG_ENTRY_PENDING_TMO;
}
}
break;
case XARP_ENTRY_OK:
if (--arp_entry.tmo == 0) {
xarp_make_request(&arp_entry.ipaddr);
arp_entry.state = XARP_ENTRY_RESOLVING;
arp_entry.tmo = XARP_CFG_ENTRY_PENDING_TMO;
}
break;
}
}
}
|
IP协议
IP层的输入处理
IP数据包结构


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| typedef struct _xip_hdr_t {
uint8_t hdr_len : 4;
uint8_t version : 4;
uint8_t tos;
uint16_t total_len;
uint16_t id;
uint16_t flags_fragment;
uint8_t ttl;
uint8_t protocol;
uint16_t hdr_checksum;
uint8_t src_ip[XNET_IPV4_ADDR_SIZE];
uint8_t dest_ip[XNET_IPV4_ADDR_SIZE];
}xip_hdr_t;
|
检验和计算
IP首部的检验和采用下面的简单计算方法:在发送方,先把IP数据报首部划分为许多16位字的序列,并把检验和字段置零。用反码算术运算把所有16位字相加后,将得到的和的反码写入检验和字段。接收方收到数据报后,将首部的所有16位字再使用反码算术运算相加一次。将得到的和取反码, 即得出接收方检验和的计算结果。若首部未发生任何变化,则此结果必为0,于是就保留这个数据报。否则即认为出差错,并将此数据报丢弃。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
static uint16_t checksum16(uint16_t * buf, uint16_t len, uint16_t pre_sum, int complement) {
uint32_t checksum = pre_sum;
uint16_t high;
while (len > 1) {
checksum += *buf++;
len -= 2;
}
if (len > 0) {
checksum += *(uint8_t *)buf;
}
while ((high = checksum >> 16) != 0) {
checksum = high + (checksum & 0xffff);
}
return complement ? (uint16_t)~checksum : (uint16_t)checksum;
}
|
IP层的输入处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| #define xipaddr_is_equal_buf(addr, buf) (memcmp((addr)->array, (buf), XNET_IPV4_ADDR_SIZE) == 0)
typedef struct _xip_hdr_t {
uint8_t hdr_len : 4;
uint8_t version : 4;
uint8_t tos;
uint16_t total_len;
uint16_t id;
uint16_t flags_fragment;
uint8_t ttl;
uint8_t protocol;
uint16_t hdr_checksum;
uint8_t src_ip[XNET_IPV4_ADDR_SIZE];
uint8_t dest_ip[XNET_IPV4_ADDR_SIZE];
}xip_hdr_t;
void xip_in(xnet_packet_t * packet) {
xip_hdr_t* iphdr = (xip_hdr_t*)packet->data;
uint32_t total_size, header_size;
uint16_t pre_checksum;
if (iphdr->version != XNET_VERSION_IPV4) {
return;
}
header_size = iphdr->hdr_len * 4;
total_size = swap_order16(iphdr->total_len);
if ((header_size < sizeof(xip_hdr_t)) || ((total_size < header_size) || (packet->size < total_size))) {
return;
}
pre_checksum = iphdr->hdr_checksum;
iphdr->hdr_checksum = 0;
if (pre_checksum != checksum16((uint16_t*)iphdr, header_size, 0, 1)) {
return;
}
if (!xipaddr_is_equal_buf(&netif_ipaddr, iphdr->dest_ip)) {
return;
}
switch(iphdr->protocol) {
default:
break;
}
}
|
在以太网层处理IP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
xether_hdr_t* hdr = (xether_hdr_t*)packet->data;
switch (swap_order16(hdr->protocol)) {
case XNET_PROTOCOL_IP: {
xip_hdr_t *iphdr = (xip_hdr_t *) (packet->data + sizeof(xether_hdr_t));
update_arp_entry(iphdr->src_ip, hdr->src);
remove_header(packet, sizeof(xether_hdr_t));
xip_in(packet);
break;
}
}
|
IP层的输出处理
IP包的输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| typedef struct _xip_hdr_t {
uint8_t hdr_len : 4;
uint8_t version : 4;
uint8_t tos;
uint16_t total_len;
uint16_t id;
uint16_t flags_fragment;
uint8_t ttl;
uint8_t protocol;
uint16_t hdr_checksum;
uint8_t src_ip[XNET_IPV4_ADDR_SIZE];
uint8_t dest_ip[XNET_IPV4_ADDR_SIZE];
}xip_hdr_t;
xnet_err_t xip_out(xnet_protocol_t protocol, xipaddr_t* dest_ip, xnet_packet_t * packet) {
static uint32_t ip_packet_id = 0;
xip_hdr_t * iphdr;
add_header(packet, sizeof(xip_hdr_t));
iphdr = (xip_hdr_t*)packet->data;
iphdr->version = XNET_VERSION_IPV4;
iphdr->hdr_len = sizeof(xip_hdr_t) / 4;
iphdr->tos = 0;
iphdr->total_len = swap_order16(packet->size);
iphdr->id = swap_order16(ip_packet_id);
iphdr->flags_fragment = 0;
iphdr->ttl = XNET_IP_DEFAULT_TTL;
iphdr->protocol = protocol;
memcpy(iphdr->dest_ip, dest_ip->array, XNET_IPV4_ADDR_SIZE);
memcpy(iphdr->src_ip, netif_ipaddr.array, XNET_IPV4_ADDR_SIZE);
iphdr->hdr_checksum = 0;
iphdr->hdr_checksum = checksum16((uint16_t *)iphdr, sizeof(xip_hdr_t), 0, 1);;
ip_packet_id++;
return ethernet_out(dest_ip, packet);
}
|
将IP数据包通过以太网发送出去
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
static xnet_err_t ethernet_out (xipaddr_t * dest_ip, xnet_packet_t * packet) {
xnet_err_t err;
uint8_t * mac_addr;
if ((err = xarp_resolve(dest_ip, &mac_addr) == XNET_ERR_OK)) {
return ethernet_out_to(XNET_PROTOCOL_IP, mac_addr, packet);
}
return err;
}
|
ICMP协议

ICMP包数据格式


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
typedef struct _xicmp_hdr_t {
uint8_t type;
uint8_t code;
uint16_t checksum;
uint16_t id;
uint16_t seq;
}xicmp_hdr_t;
|
ICMP包输入处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| #define XICMP_CODE_ECHO_REQUEST 8
#define XICMP_CODE_ECHO_REPLY 0
void xicmp_in(xipaddr_t *src_ip, xnet_packet_t * packet) {
xicmp_hdr_t* icmphdr = (xicmp_hdr_t *)packet->data;
if ((packet->size >= sizeof(xicmp_hdr_t)) && (icmphdr->type == XICMP_CODE_ECHO_REQUEST)) {
reply_icmp_request(icmphdr, src_ip, packet);
}
}
|
ICMP ECHO响应
即回应ping
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| #define XICMP_CODE_ECHO_REQUEST 8
#define XICMP_CODE_ECHO_REPLY 0
static xnet_err_t reply_icmp_request(xicmp_hdr_t * icmp_hdr, xipaddr_t* src_ip, xnet_packet_t * packet) {
xicmp_hdr_t * replay_hdr;
xnet_packet_t * tx = xnet_alloc_for_send(packet->size);
replay_hdr = (xicmp_hdr_t *)tx->data;
replay_hdr->type = XICMP_CODE_ECHO_REPLY;
replay_hdr->code = 0;
replay_hdr->id = icmp_hdr->id;
replay_hdr->seq = icmp_hdr->seq;
replay_hdr->checksum = 0;
memcpy(((uint8_t *)replay_hdr) + sizeof(xicmp_hdr_t), ((uint8_t *)icmp_hdr) + sizeof(xicmp_hdr_t),
packet->size - sizeof(xicmp_hdr_t));
replay_hdr->checksum = checksum16((uint16_t*)replay_hdr, tx->size, 0, 1);
return xip_out(XNET_PROTOCOL_ICMP, src_ip, tx);
}
typedef enum _xnet_protocol_t {
XNET_PROTOCOL_ARP = 0x0806,
XNET_PROTOCOL_IP = 0x0800,
XNET_PROTOCOL_ICMP = 1,
}xnet_protocol_t;
xnet_err_t xip_out(xnet_protocol_t protocol, xipaddr_t* dest_ip, xnet_packet_t * packet) {
static uint32_t ip_packet_id = 0;
xip_hdr_t * iphdr;
add_header(packet, sizeof(xip_hdr_t));
iphdr = (xip_hdr_t*)packet->data;
iphdr->version = XNET_VERSION_IPV4;
iphdr->hdr_len = sizeof(xip_hdr_t) / 4;
iphdr->tos = 0;
iphdr->total_len = swap_order16(packet->size);
iphdr->id = swap_order16(ip_packet_id);
iphdr->flags_fragment = 0;
iphdr->ttl = XNET_IP_DEFAULT_TTL;
iphdr->protocol = protocol;
memcpy(iphdr->dest_ip, dest_ip->array, XNET_IPV4_ADDR_SIZE);
memcpy(iphdr->src_ip, netif_ipaddr.array, XNET_IPV4_ADDR_SIZE);
iphdr->hdr_checksum = 0;
iphdr->hdr_checksum = checksum16((uint16_t *)iphdr, sizeof(xip_hdr_t), 0, 1);;
ip_packet_id++;
return ethernet_out(dest_ip, packet);
}
|
IP层处理ICMP包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| switch(iphdr->protocol) {
case XNET_PROTOCOL_ICMP:
remove_header(packet, header_size);
xicmp_in(&src_ip, packet);
break;
default:
break;
}
|
实现目标不可达的响应
ICMP的一个规则是,ICMP差错报文必须包括生成该差错报文的数据报IP首部(包含任何选项),还必须至少包括跟在该IP首部后面的前8个字节(包含源端口和目的端口)。在我们的例子中,跟在IP首部后面的前8个字节包含UDP的首部。
发送ICMP端口不可达或协议不可达的响应
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| #define XICMP_TYPE_UNREACH 3
#define XICMP_CODE_PORT_UNREACH 3
#define XICMP_CODE_PRO_UNREACH 2
xnet_err_t xicmp_dest_unreach(uint8_t code, xip_hdr_t *ip_hdr) {
xicmp_hdr_t * icmp_hdr;
xipaddr_t dest_ip;
xnet_packet_t* packet;
uint16_t ip_hdr_size = ip_hdr->hdr_len * 4;
uint16_t ip_data_size = swap_order16(ip_hdr->total_len) - ip_hdr_size;
ip_data_size = ip_hdr_size + min(ip_data_size, 8);
packet = xnet_alloc_for_send(ip_data_size + sizeof(xicmp_hdr_t));
icmp_hdr = (xicmp_hdr_t*)packet->data;
icmp_hdr->type = XICMP_TYPE_UNREACH;
icmp_hdr->code = code;
icmp_hdr->checksum = 0;
icmp_hdr->id = icmp_hdr->seq = 0;
memcpy(((uint8_t *)icmp_hdr) + sizeof(xicmp_hdr_t), ip_hdr, ip_data_size);
icmp_hdr->checksum = 0;
icmp_hdr->checksum = checksum16((uint16_t *)icmp_hdr, packet->size, 0, 1);
xipaddr_from_buf(&dest_ip, ip_hdr->src_ip);
return xip_out(XNET_PROTOCOL_ICMP, &dest_ip, packet);
}
|
UDP协议



UDP控制块
控制块负责控制进程与端口之间的操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #define XUDP_CFG_MAX_UDP 10
typedef struct _xudp_t xudp_t;
static xudp_t udp_socket[XUDP_CFG_MAX_UDP];
typedef xnet_err_t (*xudp_handler_t)(xudp_t * udp, xipaddr_t * src_ip, uint16_t src_port, xnet_packet_t * packet);
struct _xudp_t {
enum {
XUDP_STATE_FREE,
XUDP_STATE_USED,
} state;
uint16_t local_port;
xudp_handler_t handler;
};
|
UDP初始化
1 2 3 4 5 6 7 8 9 10 11
|
void xudp_init(void) {
memset(udp_socket, 0, sizeof(udp_socket));
}
|
控制块基本操作接口

打开UDP结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
xudp_t* xudp_open(xudp_handler_t handler) {
xudp_t * udp, * end;
for (udp = udp_socket, end = &udp_socket[XUDP_CFG_MAX_UDP]; udp < end; udp++) {
if (udp->state == XUDP_STATE_FREE) {
udp->state = XUDP_STATE_USED;
udp->local_port = 0;
udp->handler = handler;
return udp;
}
}
return (xudp_t *)0;
}
|
关闭UDP连接
1 2 3 4 5 6 7 8 9 10 11 12 13
|
void xudp_close(xudp_t *udp) {
udp->state = XUDP_STATE_FREE;
}
|
查找指定端口的UDP协议
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
xudp_t* xudp_find(uint16_t port) {
xudp_t * udp, * end = &udp_socket[XUDP_CFG_MAX_UDP];
for (udp = udp_socket; udp < end; udp++) {
if ((udp->state != XUDP_STATE_FREE) && (udp->local_port == port)) {
return udp;
}
}
return (xudp_t *)0;
}
|
绑定控制块到端口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
xnet_err_t xudp_bind(xudp_t *udp, uint16_t local_port) {
xudp_t * curr, * end;
if (local_port == 0) {
return XNET_ERR_PARAM;
}
for (curr = udp_socket, end = &udp_socket[XUDP_CFG_MAX_UDP]; curr < end; curr++) {
if ((curr != udp) && (curr->local_port == local_port)) {
return XNET_ERR_BINDED;
}
}
udp->local_port = local_port;
return XNET_ERR_OK;
}
|
协议栈初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
void xnet_init (void) {
ethernet_init();
xarp_init();
xip_init();
xicmp_init();
xudp_init();
}
|
UDP数据包格式



1 2 3 4 5 6 7 8 9
| typedef struct _xudp_hdr_t {
uint16_t src_port, dest_port;
uint16_t total_len;
uint16_t checksum;
}xudp_hdr_t;
|
UDP伪首部

计算UDP伪检验和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
static uint16_t checksum_peso(const xipaddr_t *src_ip, const xipaddr_t *dest_ip,
uint8_t protocol, uint16_t *buf, uint16_t len) {
uint8_t zero_protocol[2] = {0, protocol};
uint16_t c_len = swap_order16(len);
uint32_t sum = checksum16((uint16_t *)src_ip->array, XNET_IPV4_ADDR_SIZE, 0, 0);
sum = checksum16((uint16_t *)dest_ip->array, XNET_IPV4_ADDR_SIZE, sum, 0);
sum = checksum16((uint16_t *)zero_protocol, 2, sum, 0);
sum = checksum16((uint16_t *)&c_len, 2, sum, 0);
return checksum16(buf, len, sum, 1);
}
|
UDP输入处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
|
void xudp_in(xudp_t *udp, xipaddr_t *src_ip,xnet_packet_t * packet) {
xudp_hdr_t * udp_hdr = (xudp_hdr_t *)packet->data;
uint16_t pre_checksum;
uint16_t src_port;
if ((packet->size < sizeof(xudp_hdr_t)) || (packet->size < swap_order16(udp_hdr->total_len))) {
return;
}
pre_checksum = udp_hdr->checksum;
udp_hdr->checksum = 0;
if (pre_checksum != 0) {
uint16_t checksum = checksum_peso(src_ip, &netif_ipaddr, XNET_PROTOCOL_UDP,
(uint16_t *) udp_hdr, swap_order16(udp_hdr->total_len));
checksum = (checksum == 0) ? 0xFFFF : checksum;
if (checksum != pre_checksum) {
return;
}
}
src_port = swap_order16(udp_hdr->src_port);
remove_header(packet, sizeof(xudp_hdr_t));
if (udp->handler) {
udp->handler(udp, src_ip, src_port, packet);
}
}
|
在IP层处理UDP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| switch(iphdr->protocol) {
case XNET_PROTOCOL_UDP:
if (packet->size >= sizeof(xudp_hdr_t)) {
xudp_hdr_t *udp_hdr = (xudp_hdr_t *) (packet->data + header_size);
xudp_t *udp = xudp_find(swap_order16(udp_hdr->dest_port));
if (udp) {
truncate_packet(packet, total_size);
remove_header(packet, header_size);
xudp_in(udp, &src_ip, packet);
} else {
xicmp_dest_unreach(XICMP_CODE_PORT_UNREACH, iphdr);
}
}
break;
}
|
发送UDP数据包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
int xudp_out(xudp_t* udp, xipaddr_t * dest_ip, uint16_t dest_port, xnet_packet_t * packet) {
xudp_hdr_t* udp_hdr;
uint16_t checksum;
add_header(packet, sizeof(xudp_hdr_t));
udp_hdr = (xudp_hdr_t*)packet->data;
udp_hdr->src_port = swap_order16(udp->local_port);
udp_hdr->dest_port = swap_order16(dest_port);
udp_hdr->total_len = swap_order16(packet->size);
udp_hdr->checksum = 0;
checksum = checksum_peso(&netif_ipaddr, dest_ip, XNET_PROTOCOL_UDP, (uint16_t *) udp_hdr, packet->size);
udp_hdr->checksum = (checksum == 0) ? 0xFFFF : checksum;
return xip_out(XNET_PROTOCOL_UDP, dest_ip, packet);
}
|
时间返回功能
客户端向服务器通过发送一个UDP数据包申请获得当前时间, 服务器返回一个UDP数据包, 其中包含当前时间.
获取当前时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| #include <string.h>
#include <time.h>
#include "xnet_tiny.h"
#define XSERVER_DATETIME_H
xnet_err_t xserver_datetime_create(uint16_t port);
#define TIME_STR_SIZE 128
static xnet_err_t datetime_handler (xudp_t * udp, xipaddr_t * src_ip, uint16_t src_port, xnet_packet_t * packet) {
xnet_packet_t * tx_packet;
time_t rawtime;
const struct tm * timeinfo;
size_t str_size;
tx_packet = xnet_alloc_for_send(TIME_STR_SIZE);
time (&rawtime);
timeinfo = localtime (&rawtime);
str_size = strftime((char *)tx_packet->data, TIME_STR_SIZE, "%A, %B %d, %Y %T-%z", timeinfo);
return xudp_out(udp, src_ip, src_port, tx_packet);
}
xnet_err_t xserver_datetime_create(uint16_t port) {
xnet_err_t err;
xudp_t* udp = xudp_open(datetime_handler);
if (udp == (xudp_t*)0) {
return -1;
}
err = xudp_bind(udp, port);
if (err < 0) {
xudp_close(udp);
return err;
}
return 0;
}
|
TCP协议
TCP控制块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #define XTCP_CFG_MAX_TCP 40
typedef enum _xtcp_state_t {
XTCP_STATE_FREE,
XTCP_STATE_CLOSED,
XTCP_STATE_LISTEN,
}xtcp_state_t;
typedef enum _xtcp_conn_state_t {
XTCP_CONN_CONNECTED,
XTCP_CONN_DATA_RECV,
XTCP_CONN_CLOSED,
}xtcp_conn_state_t;
typedef struct _xtcp_t xtcp_t;
typedef xnet_err_t(*xtcp_handler_t)(xtcp_t* tcp, xtcp_conn_state_t event);
struct _xtcp_t {
xtcp_state_t state;
uint16_t local_port, remote_port;
xipaddr_t remote_ip;
xtcp_handler_t handler;
};
|
TCP控制块基本操作接口

分配一个TCP控制块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
static xtcp_t * tcp_alloc(void) {
xtcp_t * tcp, * end;
for (tcp = tcp_socket, end = tcp_socket + XTCP_CFG_MAX_TCP; tcp < end; tcp++) {
if (tcp->state == XTCP_STATE_FREE) {
tcp->state = XTCP_STATE_CLOSED;
tcp->local_port = 0;
tcp->remote_port = 0;
tcp->remote_ip.addr = 0;
tcp->handler = (xtcp_handler_t)0;
return tcp;
}
}
return (xtcp_t *)0;
}
|
释放一个连接块
1 2 3 4 5 6 7 8 9 10 11 12 13
|
static void tcp_free(xtcp_t* tcp) {
tcp->state = XTCP_STATE_FREE;
}
|
寻找TCP控制块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
|
static xtcp_t* tcp_find(xipaddr_t *remote_ip, uint16_t remote_port, uint16_t local_port) {
xtcp_t * tcp, * end;
xtcp_t * founded_tcp = (xtcp_t *)0;
for (tcp = tcp_socket, end = tcp_socket + XTCP_CFG_MAX_TCP; tcp < end; tcp++) {
if ((tcp->state == XTCP_STATE_FREE) || (tcp->local_port != local_port)) {
continue;
}
if (xipaddr_is_equal(remote_ip, &tcp->remote_ip) && (remote_port == tcp->remote_port)) {
return tcp;
}
if (tcp->state == XTCP_STATE_LISTEN) {
founded_tcp = tcp;
}
}
return founded_tcp;
}
|
TCP初始化
1 2 3 4 5 6 7 8 9 10 11
|
void xtcp_init(void) {
memset(tcp_socket, 0, sizeof(tcp_socket));
}
|
打开TCP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
xtcp_t * xtcp_open(xtcp_handler_t handler) {
xtcp_t * tcp = tcp_alloc();
if (!tcp) return (xtcp_t *)0;
tcp->state = XTCP_STATE_CLOSED;
tcp->handler = handler;
return tcp;
}
|
TCP控制块绑定端口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
xnet_err_t xtcp_bind(xtcp_t* tcp, uint16_t local_port) {
xtcp_t * curr, * end;
for (curr = tcp_socket, end = &tcp_socket[XTCP_CFG_MAX_TCP]; curr < end; curr++) {
if ((curr != tcp) && (curr->local_port == local_port)) {
return XNET_ERR_BINDED;
}
}
tcp->local_port = local_port;
return XNET_ERR_OK;
}
|
TCP进入监听状态
1 2 3 4 5 6 7 8 9 10 11 12 13
|
xnet_err_t xtcp_listen(xtcp_t * tcp) {
tcp->state = XTCP_STATE_LISTEN;
return XNET_ERR_OK;
}
|
关闭TCP连接
1 2 3 4 5 6 7 8 9 10 11 12 13
|
xnet_err_t xtcp_close(xtcp_t *tcp) {
tcp_free(tcp);
return XNET_ERR_OK;
}
|