一起学习
分类: LINUX
2016-08-08 20:18:13
原文地址:linux下基于ipmsg协议的飞鸽传书(一) 作者:dekee
运行机制介绍:
使用TCP/UDP端口(默认端口为2425),消息的收发使用UDP协议,文件(文件夹)的收发使用TCP协议。(文件传输部分待续....)
主函数:创建线程实现,聊天、用户上线、下线、文件传送
//===============================================================================================
//工程名称:飞鸽传书
//功能描述: 用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);
}
用到的常用命令和全局变量:
|
|
用户管理模块:
|
|