您的位置:首页 > 理论基础 > 计算机网络

IPMSG飞鸽传书5——网络协议解析手记2

2011-01-08 11:31 337 查看
每次IPMSG在收到上线通告报文后,都要查找相同ip的节点是否已经存在,只要和结构
体成员host_ip比较就可以了,这样整个用户列表当中的成员是不会重复的。报文的发送主要依靠下边的函数实现,这里推荐下边的这种写法,特别是对与命
令比较多的情况下,使用下边的好处就在与结构非常的清晰。

mode: 命令 msg: 附加信息 struct
sockaddr
*
p:网络信息
fd:网络套接字描述符


int
msg_send(
const
int
mode,
const
char
*
msg,
const
struct
sockaddr
*
p,
int
fd)

{

int
udp_fd=
fd;

int
broadcast_en=
1;

char
msg_buf[
SND_BUF_LEN]
;

char
*
use=
"test"
,
*
group=
"sunplusapp"
;

socklen_t
broadcast_len=
sizeof
(
broadcast_en)
;

long
int
msg_id=
time
(
(
time_t
*
)
NULL
)
;

struct
sockaddr_in
udp_addr;

struct
sockaddr
client;

bzero(
msg_buf,
SND_BUF_LEN)
;

bzero(
&
udp_addr,
sizeof
(
struct
sockaddr_in
)
)
;

udp_addr.
sin_family=
AF_INET
;

udp_addr.
sin_port=
htons
(
IPMSG_UDP_PORT)
;

inet_pton(
AF_INET
,
BR_IP,
&
udp_addr.
sin_addr.
s_addr)
;


//下边的if 与else if :对于上线通告
下线等使用广播地址,其他的则否

if
(
(
p=
=
NULL
)
&
&
(
mode!=IPMSG_NOOPERATION)
&
&
(
mode!=IPMSG_BR_ENTRY)
&
&
(
mode!=IPMSG_BR_EXIT)
)

{

printf
(
"p
is NULL,only mode = IPMSG_NOOPERATICNA IPMSG_BR_ENTRY IPMSG_EXIT is
allowed p=NULL /n"
)
;

return
1;

}

else
if
(
(
p!=NULL)
&
&
(
mode!=IPMSG_NOOPERATION)
&
&
(
mode!=IPMSG_BR_ENTRY)
&
&
(
mode!=IPMSG_BR_EXIT)
)

client=
*
p;


//打开广播

if
(
setsockopt
(
udp_fd,
SOL_SOCKET,
SO_BROADCAST,
&
broadcast_en,
broadcast_len)
<
0 )

{

perror
(
"setsockopt
error"
)
;

exit
(
1)
;

}

switch
(
mode)

{

case
IPMSG_NOOPERATION:

sprintf
(
msg_buf,
"1:%d:%s:%s:%d:%s"
,
msg_id,
use,
group,
mode,
NULL
)
;

sendto
(
udp_fd,
msg_buf,
strlen
(
msg_buf)
,
0,
(
struct
sockaddr
*
)
&
udp_addr,
sizeof
(
struct
sockaddr
)
)
;

break
;

case
IPMSG_BR_ENTRY:

sprintf
(
msg_buf,
"1:%d:%s:%s:%d:%s"
,
msg_id,
use,
group,
mode,
msg)
;

sendto
(
udp_fd,
msg_buf,
strlen
(
msg_buf)
,
0,
(
struct
sockaddr
*
)
&
udp_addr,
sizeof
(
struct
sockaddr
)
)
;

break
;

case
IPMSG_BR_EXIT:

sprintf
(
msg_buf,
"1:%d:%s:%s:%d:%s"
,
msg_id,
use,
group,
mode,
msg)
;

sendto
(
udp_fd,
msg_buf,
strlen
(
msg_buf)
,
0,
(
struct
sockaddr
*
)
&
udp_addr,
sizeof
(
struct
sockaddr
)
)
;

break
;

case
IPMSG_ANSENTRY:

sprintf
(
msg_buf,
"1:%d:%s:%s:%d:%s"
,
msg_id,
use,
group,
mode,
msg)
;

sendto
(
udp_fd,
msg_buf,
strlen
(
msg_buf)
,
0,
&
client,
sizeof
(
struct
sockaddr
)
)
;

break
;

case
IPMSG_SENDMSG:

sprintf
(
msg_buf,
"1:%d:%s:%s:%d:%s"
,
msg_id,
use,
group,
mode,
msg)
;

sendto
(
udp_fd,
msg_buf,
strlen
(
msg_buf)
,
0,
&
client,
sizeof
(
struct
sockaddr
)
)
;

break
;

case
IPMSG_SENDMSG_OPT:

sprintf
(
msg_buf,
"1:%d:%s:%s:%d:%s"
,
msg_id,
use,
group,
mode,
msg)
;

sendto
(
udp_fd,
msg_buf,
strlen
(
msg_buf)
,
0,
&
client,
sizeof
(
struct
sockaddr
)
)
;

break
;

case
IPMSG_RECVMSG:

sprintf
(
msg_buf,
"1:%d:%s:%s:%d:%s"
,
msg_id,
use,
group,
mode,
msg)
;

sendto
(
udp_fd,
msg_buf,
strlen
(
msg_buf)
,
0,
&
client,
sizeof
(
struct
sockaddr
)
)
;

break
;

case
IPMSG_GETFILEDATA:

sprintf
(
msg_buf,
"1:%d:%s:%s:%d:%s"
,
msg_id,
use,
group,
mode,
msg)
;

sendto
(
udp_fd,
msg_buf,
strlen
(
msg_buf)
,
0,
&
client,
sizeof
(
struct
sockaddr
)
)
;

break
;

case
IPMSG_RELEASEFILES:

sprintf
(
msg_buf,
"1:%d:%s:%s:%d:%s"
,
msg_id,
use,
group,
mode,
msg)
;

sendto
(
udp_fd,
msg_buf,
strlen
(
msg_buf)
,
0,
&
client,
sizeof
(
struct
sockaddr
)
)
;

break
;

case
IPMSG_GETDIRFILES:

sprintf
(
msg_buf,
"1:%d:%s:%s:%d:%s"
,
msg_id,
use,
group,
mode,
msg)
;

sendto
(
udp_fd,
msg_buf,
strlen
(
msg_buf)
,
0,
&
client,
sizeof
(
struct
sockaddr
)
)
;

break
;

default
:

printf
(
"no
match mode !/n"
)
;

break
;

}

broadcast_en=
0;


// 关掉广播

if
(
setsockopt
(
udp_fd,
SOL_SOCKET,
SO_BROADCAST,
&
broadcast_en,
broadcast_len)
<
0 )

{

perror
(
"setsockopt
error"
)
;

exit
(
1)
;

}

printf
(
"msg
send ok ! /n"
)
;

return
0;

}


通过上边的报文就可以实现消息的传递,可以发起文件、文件夹的传输,传输文件时,首先需要通过UDP报文联络,在UDP报文联络好之后,随即发起TCP文件传输,文件传输是不带格式的。IPMSG的一个难点就是文件夹的传输。今天就写这里,而却也做到这里。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: