如何用recvmsg和sendmsg来编写sctp的程序

如何用recvmsg和sendmsg来编写sctp的程序,第1张

I.

msghdr 与 cmsghdr

struct msghdr {

void* msg_name

int msg_namelen

struct iovec * msg_iov

unsigned long msg_iovlen

void* msg_control

unsigned longmsg_controllen

unsignedmsg_flags

}

结构成员可以分为下面的四组:

1.

套接口地址成员 msg_name 与 msg_namelen ; msg_name

指向要发送或接收信息的套接口地址。 msg_namelen 指明了这个套接口地址的长度。

msg_name 在调用 recvmsg 时指向接收地址,在调用 sendmsg 时指向目的地址。

2.

I/O 向量引用 msg_iov 与 msg_iovlen 它是实际的数据缓冲区,这个

msg_iovlen 是 msg_iov 的个数,不是长度。 msg_iov 成员指向一个

struct iovec 数组。

3.

附属数据缓冲区成员 msg_control 与 msg_controllen ,msg_control 指向附属数据缓冲区,而

msg_controllen 指明了缓冲区大小。

4.

接收信息标记位 msg_flags

struct iovec

{

void *iov_base

unsigned long iov_len

}

有了这个 iovec ,就可以使用 readv 和 writev 函数在一次函数调用中读取或是写入多个缓冲区,显然比多次 read , write 更有效率。 readv 和 writev 的函数原型如下:

#include

ssize_t writev(int fildes, const struct iovec *iov, int iovcnt)

ssize_t readv(int fildes, const struct iovec *iov, int iovcnt)

struct cmsghdr {

unsigned long cmsg_len int cmsg_level

intcmsg_type

}

· cmsg_len 附属数据的字节数,这包含结构头的尺寸,这个值是由 CMSG_LEN() 宏计算的;

· cmsg_level 表明了原始的协议级别 ( 例如, SOL_SOCKET) ;

· cmsg_type 表明了控制信息类型 ( 例如, SCM_RIGHTS ,附属数据对象是文件描述符; SCM_CREDENTIALS ,附属数据对象是一个包含证书信息的结构 )

msghdr 和 cmsghdr: Linux 系统为这些结构提供了一系列的宏来简化我们的工作,这些宏可以在不同的 UNIX 平台之间进行移植:

#include

struct cmsghdr *CMSG_FIRSTHDR(struct msghdr *msgh)

输入参数:指向 struct msghdr 结构的指针; 返回指向附属数据缓冲区内的第一个附属对象的 struct cmsghdr 指针。如果不存在附属数据对象则返回的指针值为 NULL 。

struct cmsghdr *CMSG_NXTHDR(struct msghdr *msgh, struct cmsghdr *cmsg)

输入参数:指向 struct msghdr 结构的指针,指向当前 struct cmsghdr 的指针;

这个用于返回下一个附属数据对象的 struct cmsghdr 指针,如果没有下一个附属数据对象,这个宏就会返回 NULL

size_t CMSG_SPACE(size_t length)

输入参数:附属数据缓冲区中的对象大小; 计算 cmsghdr 头结构加上附属数据大小,并包括对其字段和可能的结尾填充字符,注意 CMSG_LEN() 值并不包括可能的结尾填充字符。 CMSG_SPACE() 宏对于确定所需的缓冲区尺寸是十分有用的。 注意如果在缓冲区中有多个附属数据,一定要同时添加多个 CMSG_SPACE() 宏调用来得到所需的总空间。

void *CMSG_DATA(struct cmsghdr *cmsg)

输入参数:指向 cmsghdr 结构的指针

返回跟随在头部以及填充字节之后的附属数据的第一个字节 ( 如果存在 ) 的地址。

size_t CMSG_LEN(size_t length)

输入参数:附属数据缓冲区中的对象大小; 计算 cmsghdr

头结构加上附属数据大小,包括必要的对其字段,这个值用来设置 cmsghdr 对象的 cmsg_len 成员.

int sendmsg(int, const struct msghdr *msg, unsigned int

flags)

int recvmsg(int s, struct msghdr *msg, unsigned int flags)

s, 套接字通道,对于 sendmsg 是发送套接字,对于 recvmsg 则对应于接收套接字;

msg ,信息头结构指针;

flags , 可选的标记位, 这与 send 或是 sendto

函数调用的标记相同。

函数的返回值为实际发送 / 接收的字节数。否则返回 -1 表明发生了错误

sctp

从协议栈的角度看,于tcp,udp同等级别的层次上的。具有tcp和udp不同的优点。从传输的角度看,它可以象tcp那样点对点的那样传输,也可以像udp那样一对多那样传输,但这两种方式对于sctp来说都是建立连接的。下面就介绍这两种方式的编程方式:

UDP那样点对多点的方式(代码片段):

sctpSK = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)

error = sctp_bindx(sctpSK, (struct sockaddr *)&tempSockAddr,

1, SCTP_BINDX_ADD_ADDR)

listen(sctpSK, 1);

typedef union {

struct sctp_initmsg init

struct sctp_sndrcvinfo sndrcvinfo

} _sctp_cmsg_data_t

// buffer and variables used to read data from recvmsg control

messags

char

incmsg[CMSG_SPACE(sizeof(_sctp_cmsg_data_t))]

// data

buffer

struct

iovec iov

// the

main msghdr structure used to receive/send messages

struct

msghdr inmessage

struct

sockaddr_in msg_name

memset(&inmessage, 0, sizeof(inmessage))

iov.iov_base = malloc(SCTP_RX_BUFFER_SIZE)

if

(iov.iov_base == NULL)

{

exit(EXIT_FAILURE)

}

iov.iov_len = SCTP_RX_BUFFER_SIZE

inmessage.msg_name = &msg_name

inmessage.msg_namelen = sizeof(msg_name)

inmessage.msg_iov = &iov

inmessage.msg_iovlen = 1 //

number of iovs in the inmessage

inmessage.msg_control = incmsg

inmessage.msg_controllen =

sizeof(incmsg)

received = recvmsg(sctpSK, &inmessage, MSG_WAITALL)

解析这个收到到的inmessage相应的代码如下:

union sctp_notification {

struct

{

__u16

sn_type

__u16 sn_flags

__u32 sn_length

}

sn_header

struct

sctp_assoc_change sn_assoc_change

struct

sctp_paddr_change sn_paddr_change

struct

sctp_remote_error sn_remote_error

struct

sctp_send_failed sn_send_failed

struct

sctp_shutdown_event sn_shutdown_event

struct

sctp_adaption_event sn_adaption_event

struct

sctp_pdapi_event sn_pdapi_event

}

具体去我空间看

//*********************************************

//功能:LPC2103的UART0演示

//内容:上位机PC以9600的波特率向LPC2103发送一个字符

// LPC2103再返回该字符

#include<lpc2103.h>

#define Fosc 11059200 //晶振

#define Fcclk Fosc*5 //系统频率

#define Fpclk Fcclk/4 //PCLK

#define UART_bps 9600 //波特率

#define u8 unsigned char

//以下是函数声明

void uart_ini(void)

u8 get_char(void)

void put_char(u8)

void put_string(u8*)

int main()

{

u8 zifu

uart_ini()//UART初始化

put_string("Please input a char:")//输出字符串

while(1)

{

zifu=get_char()//接收一个字符

put_string("\nYou have sent:")

put_char(zifu)//发送该字符

}

}

//UART初始化

void uart_ini()

{

unsigned short Fdiv

APBDIV=0// Fpclk = Fcclk/4

PINSEL0=0x05//选择P0.0和P0.1为TXD0和RXD0

U0LCR=0x80//除数锁存访问位打开

Fdiv=(Fpclk/16)/UART_bps//波特率bps=(Fpclk/16)/(U0DLM:U0DLL),计算(U0DLM:U0DLL)

U0DLM = Fdiv / 256//U0DLM放除数高八位

U0DLL = Fdiv % 256//U0DLL放除数低八位

U0LCR=0x03//关闭除数锁存访问位(这时RBR,THR处于可寻址状态),并设定一个字符的位宽为8位

}

//接收一个字符

u8 get_char()

{

while((U0LSR&0x01)==0)//等待接收完成

return(U0RBR)//返回接收的字符

}

//发送一个字符

void put_char(u8 byte)

{

U0THR=byte//发送一个字符

while((U0LSR&0x40)==0)//等待发送完毕

}

//发送字符串

void put_string(u8 *p)

{

for(*p!='\0'p++) //如果不是结束符,就发送

put_char(*p)

}

//**********************************************************


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11825669.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-19
下一篇 2023-05-19

发表评论

登录后才能评论

评论列表(0条)

保存