//===============================================================================================
//工程名称:飞鸽传书
//功能描述: 用ipmsg协议实现网络聊天,用户上、下线、文件传输
//包含文件: command.c usrlist.c filelist.c srfile.c ulits.c
//作者: by dengke.
//=============================================================================================
#include <pthread.h> #include "commands.h" #include "usrlist.h" #include "filelist.h" #include "srfile.h" extern const char allHost[]; extern int msgSock; extern int tcpSock; extern PFILENODE myFileList; struct passwd *pwd; struct utsname sysName; char usrcmd[1024];
pthread_mutex_t ipmsg_mutex; //
int initServ(struct sockaddr_in *servaddr) { bzero(servaddr,sizeof(*servaddr)); msgSock=socket(AF_INET,SOCK_DGRAM,0);//AF_INET-使用ip协议族,sock_dgram使用面向无连接,0具体使用的协议由系统指定
tcpSock=socket(AF_INET,SOCK_STREAM,0);//
servaddr->sin_family=AF_INET; servaddr->sin_port=htons(IPMSG_DEFAULT_PORT);//端口使用ipmsg默认的69号端口;
servaddr->sin_addr.s_addr=htonl(INADDR_ANY); int broadcast_on=1;//打开广播选项
if (setsockopt(msgSock, SOL_SOCKET, SO_BROADCAST, &broadcast_on, sizeof(broadcast_on))<0) { printf("initSvr: Socket options brodcast set error.\n"); exit(1); } if(bind(msgSock,(struct sockaddr*)servaddr,sizeof(*servaddr))<0) { perror("initServ: bind msgsock err!\n"); exit(1); } //*
if(bind(tcpSock,(struct sockaddr*)servaddr,sizeof(*servaddr))<0) { perror("initServ: bind tcpSock err!\n"); exit(1); } if(listen(tcpSock,10)<0) { perror("initServ: listen tcpSock err!\n"); exit(1); } //*/
printf("init msgServ finshed!\n"); return 0; } //=========================================================================
//函数名称:
//功能描述:上线提示
//函数参数:
//返回值:
//==========================================================================
void loginBordCast() { MSG loginMsg; char brodcastMsg[]="wolf online!"; makeSendMsg(&loginMsg,brodcastMsg,allHost,IPMSG_BR_ENTRY); sendToMsg(msgSock,&loginMsg); return ; } //===============================================================================================
//函数名称:printOlineUsr()
//功能描述:打印在线用户
//
//================================================================================================
void printOnlineUsr() { printf("---------------------onlie usr info-------------------\n "); listUsr(stdout); printf("---------------------onlie usr info-------------------\n "); } //===================================================================================================
//函数名称:recverPthread(void *sockfd)
//功能描述:接收信息处理线程,生成在线用户列表,显示消息
//函数参数:
//返回值:
//===================================================================================================
void *recverPthread(void *sockfd) { struct sockaddr_in fromServer; char recvbuf[MAX_BUF]; char fromIp[20]; size_t fromServLen; size_t recvMsgLen; int recvSock=*(int*)sockfd; //****
MSG recvMsg; MSG retMsg; fromServLen=sizeof(fromServer); while(1) { //接收客服端信息
if(recvMsgLen=recvfrom(recvSock,recvbuf,sizeof(recvbuf),0,(struct sockaddr *)&fromServer,&fromServLen)); { inet_ntop(AF_INET,&fromServer.sin_addr.s_addr,fromIp,16); if(strcmp(fromIp,"192.168.220.211"))//自己ip不收
{ //pthread_mutex_lock(&ipmsg_mutex);//----------pthread_mutex_lock---------
msgParser(&recvMsg,recvbuf);//解释信息,将信息解析成结构体
if(((recvMsg.commandNo&IPMSG_BR_ENTRY)==1)||((recvMsg.commandNo&IPMSG_ANSENTRY)==3))//报文是用户上线提示或通报在线
{ if(!findUsrByName(recvMsg.senderName))//如果在线用户链表没有该用户则添加
{ addUsr(recvMsg.senderName,recvMsg.senderHost,fromIp);//插入一个在线用户
//printf("%s is online !\n",recvMsg.senderName);//上线提示
} } else if((recvMsg.commandNo&IPMSG_BR_EXIT)==2)//用户退出
{ if(findUsrByName(recvMsg.senderName)!=NULL) { delUsr(findUsrByName(recvMsg.senderName));//
} } else if(((recvMsg.commandNo&IPMSG_SENDMSG)==4)||(recvMsg.commandNo&0xff)==32) { //显示发送消息
//printf("%s ",recvMsg.senderName);
printf("%s(",recvMsg.senderHost); printf("%s):",fromIp); printf("%s\n",recvMsg.additional); makeSendMsg(&retMsg,"收到了",fromIp,IPMSG_RECVMSG);//收到后发回应
sendToMsg(recvSock,&retMsg); } else { } // printf("%s ",recvMsg.senderName);
// printf("%s ",recvMsg.senderHost);
// printf("%s ",fromIp);
// printf("Sendmsg=%d ",(recvMsg.commandNo&IPMSG_SENDMSG));
// printf("用户上线=%d ",(recvMsg.commandNo&IPMSG_BR_ENTRY));
// printf("tcp请求=%d ",(recvMsg.commandNo&IPMSG_GETFILEDATA));
// printf("传送文件选项=%d ",(recvMsg.commandNo&IPMSG_FILEATTACHOPT));
// printf("附件=%s\n",recvMsg.additional);
} //pthread_mutex_unlock(&ipmsg_mutex); //--------pthread_mutex_unlock----------
} } } //=================================================================================================
//函数名称:chat();
//功能描述:实现与客服端聊天
//函数参数:
//返回值:
//================================================================================================
void chat(int chatSock) { char chatbuf[1024]; char tempbuf[10]; char destIp[20]; unsigned int usrNo; USERINFO *chatUsr; MSG talkMsg; while(1) { pthread_mutex_lock(&ipmsg_mutex);//---------------pthread_mutex_lock-----
printOnlineUsr(); pthread_mutex_unlock(&ipmsg_mutex);//-------------pthread_mutex_unlock----
printf(" 'q'---to go back!\n"); printf("input a usrNo form usrlist for chat:"); fgets(tempbuf,sizeof(tempbuf),stdin); //pthread_mutex_lock();
if(!strcmp(tempbuf,"q\n")) { return; } if(!isdigit(tempbuf[0])) { printf("err!please input a usrlist num:\n"); continue; } usrNo=atoi(tempbuf); if(!isdigit(usrNo)) { pthread_mutex_lock(&ipmsg_mutex);//--------pthread_mutex_lock-----
chatUsr=findUsrByNum(usrNo); pthread_mutex_unlock(&ipmsg_mutex);//---------pthread_mutex_unlock
if(chatUsr) //找到聊天的对象
{ strcpy(destIp,chatUsr->ipaddr);
while(1) { //与选定的usr聊天
printf("destIp(%s):",destIp); memset(chatbuf,0,sizeof(chatbuf)); //pthread_mutex_unlock();
fgets(chatbuf,sizeof(chatbuf),stdin); //pthread_mutex_lock();
if(!strcmp(chatbuf,"q\n"))//退出聊天,返回上一级目录
{ break; } pthread_mutex_lock(&ipmsg_mutex);//---------pthread_mutex_lock-------
makeSendMsg(&talkMsg,chatbuf,destIp,IPMSG_SENDMSG); sendToMsg(chatSock,&talkMsg); pthread_mutex_unlock(&ipmsg_mutex);//---------pthread_mutex_unlock---
} } else { printf("you select usr is not online\n"); continue; } } else { printf("your input usrNo is not digit!\n"); continue; } //pthread_mutex_unlock();
} } //=================================================================================================
//函数名称:
//功能描述:打印帮助信息
//函数参数:
//返回值:
//==================================================================================================
void printFunMenu() { printf("****************function menu******************\n"); printf(" 'ls'---list all online usr \n"); printf(" 'chat'---begin to chat \n"); printf(" 'sf'---sendfile example: sf file1 file2 \n"); printf(" 'rf'---recvsfile example: rf file1 file2 \n"); printf(" 'help'---help info \n"); printf(" 'exit'---quit system \n"); printf("****************function menu******************\n"); }
//=================================================================================================
//函数名称:usrTalkPthread(void *sockfd)
//功能描述:线程、接收用户输入
//函数参数:
//返 回 值:
//===================================================================================================
void *getCmdPthread(void *sockfd) { int talkSock=*(int *)sockfd; char rfcmdbuf[100]; char *arg[100]; char usrno[20]; USERINFO *selectuser; while(1) { printf("\r "); printf("\r select your command:"); fgets(usrcmd,sizeof(usrcmd),stdin); //pthread_mutex_lock();
if(!strcmp(usrcmd,"ls\n")) { pthread_mutex_lock(&ipmsg_mutex);//-----pthread_mutex_lock-----
printOnlineUsr(); pthread_mutex_unlock(&ipmsg_mutex); //----pthread_mutex_unlock
} else if(!strcmp(usrcmd,"chat\n")) { chat(talkSock);//
} else if(!strcmp(usrcmd,"help\n")) { printFunMenu(); } else if(!strcmp(usrcmd,"exit\n")) { perror("in exit\n"); exit(1); } else if(!strcmp(usrcmd,"sf\n")) { //----------------------------pthread_mutex_lock-------------
pthread_mutex_lock(&ipmsg_mutex); printOnlineUsr(); pthread_mutex_unlock(&ipmsg_mutex); //--------prhread_mutex_unlock
printf("input command:sf usrNo filename\n"); printf("example:sf 1 file1 file2 ...\n"); fgets(rfcmdbuf,sizeof(rfcmdbuf),stdin); //---------------------------------pthread_mutex_lock---------
pthread_mutex_lock(&ipmsg_mutex); rfcmdbuf[strlen(rfcmdbuf)-1]='\0'; int count=0; count=strSplit(rfcmdbuf," ",arg); if(!isdigit(atoi(arg[1]))&&(count<2)) { printf("command is bad commad!\n"); continue; } //printf("arg[1]=%s arg[2]=%s\n",arg[1],arg[2]);
//printf("before makefilelist\n");
// int i=2;
// while(arg[i])
// {
// printf("arg[%d]=%s\n",i,arg[i]);
// i++;
// }
makeFileList(arg);//生成文件列表
//printf("after makefilelist\n");
listFile(stdout); strcpy(usrno,arg[1]); selectuser=findUsrByNum(atoi(usrno));//获得选定的用户信息
sendFileList(talkSock,selectuser,myFileList); //---------------------------------pthread_mutex_unlock---------
pthread_mutex_unlock(&ipmsg_mutex); } else if(!strcmp(usrcmd,"rf\n")) { } else { printf("command '%s' is not found!",usrcmd); } //pthread_mutex_unlock();
} } //void *recvFilePthread(void *sockfd)
//{
// int connfd;
// struct sockaddr_in clientAddr;
// size_t clientLen=sizeof(clientAddr);
// char databuf[1024];
// size_t recvLen;
// connfd=accept(tcpSock,(struct *)&clientAddr,(socklen_t *)&clientLen);
// while(1)
// {
// if((recvLen=read(tcpSock,databuf,sizeof(databuf)))>0)
// {
//
// }
// }
//}
//==================================================================================================
//函数名称:
//功能描述:接收文件传输(完成中......)
//函数参数:
//返回值:
//==================================================================================================
void *recvFilePthread(void *sockfd) { char recvbuf[1024]; int connfd; int clientSock=*(int *)sockfd; struct sockaddr_in clientServer; size_t client_len=sizeof(clientServer); size_t recvLen; connfd=accept(clientSock,(struct sockaddr *)&clientServer,&client_len); while(1) { if((recvLen=read(connfd,recvbuf,sizeof(recvbuf)))>0) { printf("recvbuf=%s\n",recvbuf); } else { break; } } close(clientSock); } //=============================================================================================
//函数名称:
//功能描述:创建线程实现,聊天、用户上线、下线、及文件传送
//函数参数:
//返回值:
//==============================================================================================
int main(int argc,char *argv[]) { struct sockaddr_in msgServer; pthread_t recvMsg,usrCmd,recvFile,sendFile; pthread_mutex_init(&ipmsg_mutex,NULL); initServ(&msgServer); initUsrList(); pwd=getpwuid(getuid());//***
uname(&sysName); //***
loginBordCast();//广播通知上线
printFunMenu(); memset(usrcmd,0,sizeof(usrcmd));
pthread_create(&recvMsg,NULL,(void *)*recverPthread,&msgSock); pthread_create(&usrCmd,NULL,(void *)*getCmdPthread,&msgSock); //pthread_create(&recvFile,NULL,(void *)*recvFilePthread,&tcpSock);
//pthread_create(&sendFile,NULL,(void *)*sendFilePthread,&tcpSock);
pthread_join(recvMsg,NULL); pthread_join(usrCmd,NULL); //pthread_join(recvFile,NULL);
}
|