量型,但也同时意味着原始套接字继承了\原始线程\的功能限制.每个原始套接字只能生存于单个函数中.自动变量(栈变量)不能跨原始套接字函数调用存在. 注意:
由于原始套接字库使用的是\原始线程(protothreads)\在调用原始套接字库函数时,局部变量并不总能得到保存.所以这里建议局部变量的使用要十分小心。
原始套接字库提供了一些无需处理重传和回应的发送数据函数,和一些无需对被分解成多个TCP段的数据进行处理的读取数据函数。
由于每个原始套接字都作为一个“原始线程”来运行,应在使用原始套接字的函数起始处通过调用PSOCK_BEGIN() 的方式启用原始套接字。与之类似,原始套接字可以通过调用PSOCK_EXIT()结束掉。 相关文件:
psock.h 原始套接字库头文件 相关结构体:
struct psock_bufstruct psock 代表一个原始套接字。
#define PSOCK_INIT(psock, buffer, buffersize) 初始化一个原始套接字。
#define PSOCK_BEGIN(psock) 在一个函数中启用一个原始套接字的原始线程。 #define PSOCK_SEND(psock, data, datalen) 发送数据。
#define PSOCK_SEND_STR(psock, str) 发送一个以零结尾的字符串。
#define PSOCK_GENERATOR_SEND(psock, generator, arg) 通过函数(generator)产生数据并发送出去。
#define PSOCK_CLOSE(psock) 关闭一个原始套接字。 #define PSOCK_READBUF(psock) 读数据直到缓冲区满。 #define PSOCK_READTO(psock, c) 读数据到字符c.
#define PSOCK_DATALEN(psock) 获得上次读到的数据长度。 #define PSOCK_EXIT(psock) 退出原始套接字的原始线程。
#define PSOCK_CLOSE_EXIT(psock) 关闭一个原始套接字,并退出其原始线程。 #define PSOCK_END(psock) 声明一个原始套接字的原始线程的结尾。 #define PSOCK_NEWDATA(psock) 查明是否有数据到达原始套接字。
#define PSOCK_WAIT_UNTIL(psock, condition) 等待,直到条件(condition)为真。 #define PSOCK_WAIT_THREAD(psock, condition) PT_WAIT_THREAD(&((psock)->pt), (condition))
u16_t psock_datalen(struct psock *psock) char psock_newdata(psock * s)
追加:
1. #define PSOCK_BEGIN(psock) 启用一个原始套接字的原始线程。
此宏启用一个原始套接字关联的原始线程,必须在使用此原始套接字的函数调用其他原始套接字函数之前出现。 参数:
psock (struct psock *)指向要启用的原始套接字的结构体指针。 应用例程:
hello-world.c, and smtp.c. 定义于psock.h的158行.
2. #define PSOCK_CLOSE(psock)
此宏用于关闭一个原始套接字,只能用于此原始套接字生存的原始线程中. 参数:
psock (struct psock *)指向要关闭的原始套接字的结构体指针。 应用例程:
hello-world.c, and smtp.c.
定义于psock.h的235行.
3. #define PSOCK_CLOSE_EXIT(psock)
此宏用于关闭一个原始套接字,并退出原始套接字生存的线程. 参数:
psock (struct psock *)指向要关闭的原始套接字的结构体指针。 定义于psock.h的308行.
4. #define PSOCK_DATALEN(psock)
返回之前通过 PSOCK_READTO() 或 PSOCK_READ()读到的数据长度. 参数:
psock (struct psock *)指向盛放数据的原始套接字的结构体指针。 定义于psock.h的281行. 5. #define PSOCK_END(psock)
此宏用于声明原始套接字的原始线程结束.常于PSOCK_BEGIN(psock)配合使用. 参数:
psock (struct psock *)指向原始套接字的结构体指针 应用例程:
hello-world.c, and smtp.c. 定义于psock.h的325行.
6. #define PSOCK_EXIT(psock)
此宏用于终止原始套接字的原始线程,必须与PSOCK_CLOSE一起使用. 也可以直接使用PSOCK_CLOSE_EXIT(); 参数:
psock (struct psock *)指向原始套接字的结构体指针. 应用例程: smtp.c.
定义于psock.h的297行.
7. #define PSOCK_GENERATOR_SEND(psock,generator,arg) 通过函数产生数据并发送. 参数:
psock 指向原始套接字的指针. generator 指向产生数据的函数的指针. arg 要传给函数的参数.
使宏用于通过函数产生数据,并通过原始套接字发送.它可以用于动态产生数据并传输,而不必先将产生的数据存入缓冲区.此函数减小了缓冲区内存的开销.产生器函数由应用程序实现,使用时要将函数的指针作为一个参数传给宏. 产生器函数应该将产生的数据直接存放在uip_appdata缓冲区中,并返回产生数据的长度.数据每一次发送时,原始套接字层会调用产生器函数,并且如果出现重发的情况,则也会调用一次产生器函数,也就是说重发的值并非第一次产生器函数调用时的值.
定义于psock.h的219行.
8. #define PSOCK_INIT(psock ,buffer,buffersize)
这个宏初始化一个原始套接字,它必须在使用套接字之间得到调用. 此宏还规定了套接字的输入缓冲区. 参数:
psock (struct psock *) 指向要初始化的原始套接字的指针. buffer (char * ) 指向原始套接字的输入缓冲区的指针. buffersize (unsigned int) 输入缓冲区的大小. 应用例程:
hello-world.c, and smtp.c. 定义于psock.h的144行.
9. #define PSOCK_NEWDATA(psock) 此宏用于查明是否有数据到达套接字。
它常和PSOCK_WAIT_UNTIL() 连用,查看套接字上是否有新的数据到达。 参数:
psock (struct psock *) 指向套接字的指针。 定义于psock.h的339行。
10. #define PSOCK_READBUF(psock) 读数据直到缓冲区满。
此宏会阻塞数据等待,把数据读入由PSOCK_INIT()指定的输入缓冲区。读数据操作会进行到缓冲区满为止。
参数:
psock (struct psock *) 指向数据读取来源套接字的指针。 定义于psock.h的250行。
11. #define PSOCK_READTO(psock,c) 读数据直到某字符出现。
此宏会阻塞数据等待并开始读取数据到由PSOCK_INIT()指定的输入缓冲区,数据读取会一直持续到由参数c指定的字符出现为止。 参数:
psock (struct psock *)指向数据读取来源套接字的指针。 c (char )用于指示停止读取数据的字符。 应用例程:
hello-world.c, and smtp.c. 定义于psock.h的268行。
12. #define PSOCK_SEND(psock,data,datalen) 发送数据。
此宏通过原始套接字发送数据。原始套接字阻塞原始线程,直到所有的数据发送完毕,并且已经被完程TCP终端接收。 参数:
psock (struct psock *) 指向用于发送数据的原始套接字的指针。 data (char *) 指向要发送的数据的指针。 datalen (unsigned int)要发送的数据长度。 应用例程: smtp.c.
定义于psock.h的178行。
13. #define PSOCK_SEND_STR(psock,str) 发送一个以零结尾的字符串。 参数:
psock (struct psock *) 指向要用来发送数据的套接字指针。 str 要发送的字符串。 应用例程:
hello-world.c, and smtp.c.
定义于psock.h的191行。
14. #define PSOCK_WAIT_UNTIL(psock,condition) 等待直接条件为真。
下宏阻塞原始线程,直到条件为真。宏PSOCK_NEWDATA()可以用来检查此宏等待时有没有新数据到来。 此宏的典型用法如下:
1. 2. 3. 4. 5. 6. 7. 8. 9.
PT_THREAD(thread(struct psock *s, struct timer *t)) {
PSOCK_BEGIN(s);
PSOCK_WAIT_UNTIL(s, PSOCK_NEWADATA(s) || timer_expired(t));
if(PSOCK_NEWDATA(s)) { PSOCK_READTO(s, '\\n'); } else {
10. handle_timed_out(s); 11. } 12.
13. PSOCK_END(s); 14. }
复制代码 参数:
psock (struct psock *)套接字指针。 condition 等待条件。 定义于psock.h的372行。
UIP中文文档第六 uIP原始线程(protothreads)
详细说明:“原始线程”是一种轻量级的、无需堆栈的线程。它主要用于内存极为受限的系统,如深入嵌入式系统、传感器网络等。
“原始线程”是以C代码实现的,为事件驱动的系统提供了线性的代码执行空间。“原始线程”即可以用在有实时操作系统的系统中,也可以用在没有实时操作系统的系统中。
它在事件驱动的系统上层提供了阻塞上下文,省去了每个线程的单独堆栈空间开销。原始线程的目标是在没有复杂的状态机或多线程的情况下实现控制顺序流。原始线程在C语言内部实现了条件阻塞。
原始线程相对于纯事件驱动方法的优势是原始线程提供了可以阻塞函数的顺序代码结构。在纯事件驱动的方法中,阻塞的实现必须将一个函数手动分成两个部分。一部分放在阻塞调用前,一部分放在阻塞调用后。这让使用if()和while()语句变得困难。
原始线程相对于普通线程的优势是,它不需要为每个线程分配堆栈。在内存受限的系统中,为每个线程分配堆栈空间会占用大量的内存。相比而言,原始线程的每个线程只需2到12个字节的状态字,具体多大与构架有关。 注意:
由于原始线程有阻塞调用中中不需保存堆栈上下文,原始线程阻塞时,局部变量也不再保留。这意味着局部变量的使用