以下是我从别的blog上转载的, 关于Linux下的飞鸽简要设计框架, 之所以说是Linux下的, 因为代码是Linux下的. 但是, 设计框架将遵循windows版飞鸽传书的协议和框架.数据包格式:
版本号:包编号:用户名:机器名:命令字:附加信息
如 1:2067943:liu :d14:32:hello
以上是一个发送消息的数据包格式,其中32是标示的发消息命令字。附加信息会随着命令字的不同而有所不同,例如,当对方发送了一条消息,你需要返回确认消息时,就需要在附加信息位置加上对方给你发消息时的包编号,只有包编号正确,对方才不会重发。
整个过程都要以以上数据包格式发送数据,因此,将数据包定义为一个结构体
typedef struct cmd
{
Unsigned int verision;
Unsigned int packetno;
Char sendName[];
Char machineName[];
Unsigned int fcommandNo; //命令字
Struct socketaddr_in peer; //这是套接字信息存储结构体
}CMD;
为了将实时的在线用户信息返回,就需要建立一个用户链表,
用户信息存储结构体如下:
Typedef struct info
{
Int no;
Char user[];
Char machine[];
Char IP[];
Struct info *next;
}INFO;
做完以上工作,接下来将进行总体的架构。因为,总体架构不合格,将会直接影响后面工作的进行。通过二次重写,使我深刻认识到,功能函数的重要性,在一个项目中,有时会对某一功能块进行多次调用,但你又不知道具体使那一块,这是跟着项目进度才可准确知道的。因而,为了方便,就要将一个功能封装成一个功能函数,这即有利于程序的可读性,又使得程序的架构变得容易些。
首先,我们需要知道本地的用户名等信息,这是用来填充CMD结构体中的用户名和机器名信息。这里有用到的两个函数实例
#include<pwd.h>
#include<sys/utsname.h>
Struct passwd *pwd;
Struct utsname sysName;
uname(&syaName);
pwd = getpwuid(getuid());
通过上面的操作,已经将用户名存入pwd-->pw_name;机器名存入sysName.nodename中。
在进行聊天或者文件传书时,我们需要用到服务器模式,其实udp 服务器模式在一开始就要涉及到,如recvfrom()将作为服务器阻塞,以便等待接收广播后的回送信息,来建立用户列表。所以initSrv ()函数完成tcp 和udp 服务器的初始化。也就是这里有Udp绑定操作和tcp的绑定,监听操作。
下面将要并行完成命令选择(即ls--列出在线用户,tk--和某人聊天)和消息接收。着里会创建两个线程,一线程(tid1)用来进行命令控制,如,ls--则列举在线用户的所有信息(结构体INFO),具体代码见下边。另一个线程(tid2)则是用recvfrom()阻塞函数来接收网络数据,根据接收到的不同命令字去执行不同的功能函数。例如,命令字为1或3时,将用户加入信息链表,为2时将用户从链表中删除。等等。。。
本代码只实现了以上的一些功能,即聊天,显示在线用户信息,自动删除下线用户。文件的传送代码没有完成,这里讲述架构思路。
在上面的基础上,我们在主线程中已经创建了两个线程,接着用accept()来阻塞等待某方的tcp连接(connect)。线程tid1中可设置发送文件(主动行为,通过udp发送请求命令字),对方同意接收文件后,就会自动连接(connect())accept(),当有人链接到我的tcp 时,表示要传送文件,这时创建一个线程来接收文来发送文件。当在线程tid2中受到某方的发文件请求,当选择同意后,自动连对方tcp服务器来接收文件。只在传送文件数据时才使用tcp协议。在设计实现中还存在很多细节问题,这个在具体设计中在考虑。
代码:
#ifndef _MESSAGE_
#define _MESSAGE_
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<net/if.h>
#include<sys/utsname.h>
#include<string.h>
typedef struct info
{
int no;
char user[20];
char machine[20];
char IP[16];
// struct sockaddr_in newaddr;
struct info *next;
}INFO;
typedef struct cmd
{
unsigned int version;
unsigned int packetno;
char senderName[30];
char machineName[40];
unsigned int commandNo;
char addtionInfo[500];
struct sockaddr_in peer;
}CMD;
extern int msgsock;
extern int tcpsock;
extern struct passwd* pwd;
extern struct utsname sysName;
extern void initSrv();
extern void initcmd(CMD *cmd,int flag);
extern void sendMsg(CMD *cmd,char *addtionInfo);
extern void strcut(char *ptr[],char *buf);
extern int listUsr(FILE *file);
#endif
//---------------------------------------------------------------------------------
#include"message.h"
#include<string.h>
#include<pthread.h>
#include<sys/types.h>
#include<pwd.h>
static int menno=1;
int msgsock,tcpsock;
struct passwd *pwd;
struct utsname sysName;
struct info *head=NULL,*pf=NULL;
void dlt_user(char *IP);
void add_user(char *username,char *machine,char *IP);
void list_user();
void talk(int no);
void *ctrcmd()
{
CMD cmd;
char info[500];
char fromIP[16]="255.255.255.255";
char buf[40]="";
int no;
initcmd(&cmd,1);
cmd.peer.sin_port=htons(2425);
cmd.peer.sin_family=AF_INET;
inet_pton(AF_INET,fromIP,&cmd.peer.sin_addr.s_addr);
strcpy(info,"liu");
sendMsg(&cmd,info);
while(1)
{
printf("input:");
fflush(stdout);
// fgets(buf,40,stdin);
scanf("%s",buf);
// buf[strlen(buf)-1]='/0';
if(strcmp(buf,"ls")==0)
list_user();
else if(strcmp(buf,"tk")==0)
{
// printf("please choice:");
// fflush(stdout);
scanf("%d",&no);
getchar();
talk(no);
//-----------
}
else if(strcmp(buf,"exit")==0)
{
initcmd(&cmd,2);
// inet_pton(AF_INET,fromIP,&cmd.peer.sin_addr.s_addr);
strcpy(info,"liu");
sendMsg(&cmd,info);
exit(0);
}
}
}
void *process()
{
CMD cmd;
struct sockaddr_in fromaddr;
int fromlen,fromfd;
int command;
char *ptr[10];
char IP[16]="";
char buf[1024];
while(1)
{
fromlen = sizeof(struct sockaddr);
if((fromfd = recvfrom(msgsock,buf,1024,0,(struct sockaddr*)&fromaddr,&fromlen))== -1)
{
perror("recv error!");
}
strcut(ptr,buf);
inet_ntop(AF_INET,&fromaddr.sin_addr.s_addr,IP,16);
printf("IP:%s/n",IP);
command =atoi( ptr[4])&0x000000ff;
printf("command:%d/n",command);
if(command==1||command== 3)
{
add_user(ptr[2],ptr[3],IP);
}
else if(command==2 )
{
dlt_user(IP);
}
else if(command == 32)
{
printf("%s:%s/n",ptr[2],ptr[5]);
initcmd(&cmd,33);
cmd.peer.sin_port = fromaddr.sin_port;
inet_pton(AF_INET,IP,&cmd.peer.sin_addr.s_addr);
sprintf(buf,"%s",ptr[1]);
sendMsg(&cmd,buf);
}
}
pthread_exit(NULL);
}
void talk(int no)
{
CMD cmd;
struct info *temp;
char buf[100]="";
int flag=0;
if(head == NULL)
{
printf("no one online!/n");
return ;
}
temp = head;
while(temp != NULL)
{
if(temp->no==no)
{
flag = 1;
cmd.peer.sin_port=htons(2425);
cmd.peer.sin_family=AF_INET;
inet_pton(AF_INET,temp->IP,&cmd.peer.sin_addr.s_addr);
break;
}
else
temp = temp->next;
}
if(flag==0)
{
printf("no that element!/n");
return;
}
while(1)
{
printf("MSG:");
memset(buf,0,sizeof(buf));
fgets(buf,100,stdin);
buf[strlen(buf)-1]='/0';
if(strcmp(buf,"quit")==0)
{
initcmd(&cmd,33);
sendMsg(&cmd,buf);
break;
}
initcmd(&cmd,32);
sendMsg(&cmd,buf);
}
}
void sendMsg(CMD *cmd,char *addtionInfo)
{
char buf[600];
if(addtionInfo == NULL)
strcpy(cmd->addtionInfo,"");
else
strcpy(cmd->addtionInfo,addtionInfo);
sprintf(buf,"%d:%d:%s:%s:%d:%s",cmd->version,cmd->packetno,cmd->senderName,cmd->machineName,cmd->commandNo,cmd->addtionInfo);
if( sendto(msgsock,buf,strlen(buf),0,(struct sockaddr*)&cmd->peer,sizeof(cmd->peer)) == -1)
{
perror("send error!");
}
return ;
}
void strcut(char *ptr[],char *buf)
{
char *token=NULL;
char *str=":";
int i=0;
if(buf==NULL)
return ;
token = strtok(buf,str);
ptr[0]=token;
while(token != NULL)
{
ptr[i++]=token;
token = strtok(NULL,str);
}
return;
}
void add_user(char *username,char *machine,char *IP)
{
struct info *pb,*tmphead;
tmphead = head;
printf("start here!/n");
while(tmphead != NULL)
{
if(strcmp(tmphead->IP,IP)==0)
{
printf("if here!/n");
return ;
}
else
tmphead = tmphead->next;
}
printf("malloc here!/n");
pb = (struct info*)malloc(sizeof(struct info));
pb->no=menno++;
strcpy(pb->user,username);
strcpy(pb->machine,machine);
strcpy(pb->IP,IP);
if(head==NULL)
{
printf("add head here!/n");
head=pf=pb;
pb->next = NULL;
}
else
{
printf("addr pf here!/n");
pf->next = pb;
pb->next = NULL;
pf = pb;
}
}
void list_user()
{
struct info *tmp;
if(head==NULL)
return ;
tmp = head;
while(tmp!=NULL)
{
printf("NO:%d ",tmp->no);
printf("USER:%s ",tmp->user);
printf("MACH:%s ",tmp->machine);
printf("IP:%s/n",tmp->IP);
tmp = tmp->next;
}
}
void dlt_user(char *IP)
{
struct info *temp,*tphead;
// int flag=0;
if(head==NULL)
return;
temp=tphead=head;
while(tphead != NULL )
{
if(strcmp(tphead->IP,IP)==0)
break;
temp=tphead;
tphead=tphead->next;
}
if(tphead == NULL)
return ;
if(head==tphead && tphead->next==NULL)
{
head=NULL;
menno--;
free(tphead);
}
else if(head == tphead && tphead->next!=NULL)
{
head = tphead->next;
temp =tphead->next;
while(temp !=NULL)
{
temp->no--;
temp=temp->next;
}
menno--;
free(tphead);
}
else if(head != tphead && tphead->next != NULL)
{
temp->next = tphead->next;
temp=tphead->next;
while(temp !=NULL)
{
temp->no--;
temp=temp->next;
}
menno--;
free(tphead);
}
else
{
pf=temp->next = NULL;
menno--;
free(tphead);
}
}
void initcmd(CMD *cmd,int flag)
{
if(cmd == NULL)
return;
bzero(cmd,sizeof(cmd));
cmd->version=1;
cmd->packetno=(unsigned int)time(NULL);
strcpy(cmd->senderName,pwd->pw_name);
strcpy(cmd->machineName,sysName.nodename);
cmd->commandNo = flag;
return;
}
void initSrv()
{
struct sockaddr_in server;
int broadcast_en = 1;
msgsock = socket(AF_INET,SOCK_DGRAM,0);
tcpsock = socket(AF_INET,SOCK_STREAM,0);
server.sin_family = AF_INET;
server.sin_port = htons(2425);
server.sin_addr.s_addr = htonl(INADDR_ANY);
if( setsockopt(msgsock,SOL_SOCKET,SO_BROADCAST,&broadcast_en,sizeof(broadcast_en))==-1)
{
printf("broadcast setsockopt error!/n");
exit(1);
}
if(bind(msgsock,(struct sockaddr*)&server,sizeof(struct sockaddr))!=0)
{
perror("udp bind error!");
exit(1);
}
if(setsockopt(tcpsock,SOL_SOCKET,SO_REUSEADDR,&broadcast_en,sizeof(broadcast_en))==-1)
{
printf("tcp setsock error!/n");
exit(1);
}
if(bind(tcpsock,(struct sockaddr*)&server,sizeof(struct sockaddr))!=0)
{
perror("tcp bind error!");
exit(1);
}
if(listen(tcpsock,10)!=0)
{
perror("listen error!");
exit(1);
}
}
int main()
{
pthread_t tid1,tid2;
uname(&sysName);
pwd = getpwuid(getuid());
initSrv();
if(pthread_create(&tid1,NULL,(void *)*ctrcmd,NULL)!=0)
{
perror("pthread creat error!");
exit(1);
}
if(pthread_create(&tid2,NULL,(void *)*process,NULL)!=0)
{
perror("pthread creat error!");
exit(1);
}
while(1)
{
}
return 0;
}