- 论坛徽章:
- 0
|
今天把关于socket, port和queue的关系理了一下,并改写了相应的代码。
首先,一个socket应该是和一个port一一对应的,但是两个数据结构在概念上不能混为一谈,事实上我认为socket应该是port的超集,一个port和与之对应的IP地址组成的二元组才称其为一个socket。因此我们将定义一个关于port的数据结构:port_info, 并在socket结构体里面添加这个成员,使得这个层次关系显得更加明显。
port_info结构体如下:
struct port_info
{
u16 port_num;
u8 type;
struct list_node tx_qu, rx_qu;
struct list_node node;
};
并且在struct socket中添加了一个 struct port_info *port 的成员。
随后我们为port新增了四个函数,当然不一定都和struct port_info有关,有些函数仅仅只是获得一个端口号而已。
四个函数分别如下:
u16 get_port(u8 type)
{
int ret;
u16 port;
port = 2134 + port_cnt;
port_cnt += 5;
for (; port < 65536; port += 200)
{
ret = check_port(port, type);
if (!ret)
return port;
}
return -EINVAL;
}
int check_port(u16 port, u8 type)
{
struct list_node *iter;
struct port_info *curr_port;
list_for_each(iter, &g_curr_ports)
{
curr_port = OFF2BASE(iter, struct port_info, node);
if (port == curr_port->port_num)
{
if (type == curr_port->type)
{
return -EBUSY;
}
}
}
return 0;
}
struct port_info *init_port(u16 num, u8 prot_type)
{
struct port_info *port;
port = (struct port_info *)malloc(sizeof(struct port_info));
if (NULL == port)
{
printf("%s(): error %d\n", __FUNCTION__, __LINE__);
return NULL;
}
port->port_num = num;
port->type = prot_type;
list_head_init(&port->tx_qu);
list_head_init(&port->rx_qu);
list_add_tail(&port->node, &g_curr_ports);
return port;
}
void del_port(u16 num)
{
struct list_node *iter;
struct port_info *curr_port;
list_for_each(iter, &g_udp_ports)
{
curr_port = OFF2BASE(iter, struct port_info, node);
if (num == curr_port->port_num)
list_del_node(iter);
}
}
说明一下:
port_cnt是一个全局变量, 主要是为进程分配随即端口时的一个参变量,每一次被操作后会增加一个步长,考虑到目前g-bios或者说bootloader中端口的使用量不大,所以没处理端口号溢出的情况。
get_port()是一个简单获得端口的算法,参数type是标明是哪种协议的端口比如TCP,UDP以及SCTP,下面各函数的的此参数意思也是一样的。
check_port函数是用来检查当前端口是否可用。
init_port()用来初始化port_info结构体,目前在UDP通信中,它将在socket()函数中被执行,不过我觉得把它改名为alloc_port_info()会比较好。del_port()则是逆操作,用来释放这个结构体,对应地,它也应该更名为free_port_info()好点。
今天主要就做了这些,中间好像还修修改改了些地方,都是小问题也记不清了, 明天要开始写TCP协议了,今晚要好好看看规范。 |
|