logo资料库

linux系统_局域网通信软件.doc

第1页 / 共27页
第2页 / 共27页
第3页 / 共27页
第4页 / 共27页
第5页 / 共27页
第6页 / 共27页
第7页 / 共27页
第8页 / 共27页
资料共27页,剩余部分请下载后查看
局域网通信软件——by liaoye928 /************************************************************ 功能 A,私聊 B,群聊,C,从服务器下载文件 D,上传文件到服务器,E,用户上下线通知 , F,刷新在线用户列表,E,下线 /* See NOTES */ 1,一般情况请使用 SUDO 权限运行 2,服务器文件中心路径为 /home/file_centre ,若没有该文件夹,请创建 3,客户端下载到的文件保存路径为 /home/file_download 使用该功能前,请先创建该文件夹 4,请在 linux 环境下测试运行(我使用的是 ubuntu) *****************************************************************/ /*头文件*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAXSIZE 512 /*服务器接收消息后,创建的在线用户列表*/ struct user_info{ id; char user_name[20]; int struct sockaddr_in cli_addr; struct user_info *next; }; /*客户端给服务器发送的消息*/ struct msg { char type; char self_name[20]; char dst_name[20]; char data[MAXSIZE]; }; /*消息类型定义*/ 1
局域网通信软件——by liaoye928 //要求刷新用户在线用户(重新打印在线用户) //私聊消息 //群聊消息 //从服务器下载文件(下载之前先打印文件列表) //上传文件到服务器 //登录 enum msg_type{ LOG_IN = 1, REFRESH, CHAT_PRI, CHAT_ALL, DOWNLOAD, UPLOAD, OFFLINE, OVER, ERROR, FILE_NAME, FILE_ERROR//选择文件名失败 //下线通知 //服务器发送本次消息结束 //重复登录 //发送文件列表 }; /*服务器总列表*/ struct servmsg { struct msg recvmsg; struct sockaddr_in addr; struct servmsg *next; }; /*客户端源程序 --liaoye928*/ #include"include.h" static int cli_fd = -1; //主要套接字,用于接受服务器各种消息 static int sock_fd = -1; //组播套接字,用于群聊 static struct sockaddr_in serv_addr; //用于存储服务器 IP 和端口 static char myname[20]; //用于存储用户名 static pthread_t tid4 = -1; //将其定义为全局变量的原因是,接收线程会将其取消 /*创建数据报套接字函数*/ int udp_link(void) { int sock_fd; sock_fd = socket(AF_INET,SOCK_DGRAM,0); return sock_fd; } /*用于给服务其发送数据的函数*/ void send_sig(char myname[],char desname[],char data[],struct sockaddr_in serv_addr,char ch) { struct msg mymsg; mymsg.type = ch; if(myname != NULL) strcpy(mymsg.self_name,myname); 2
局域网通信软件——by liaoye928 if(desname != NULL) strcpy(mymsg.dst_name, desname); if(data != NULL) strcpy(mymsg.data, data); if(sendto(cli_fd,&mymsg,sizeof(struct *)&serv_addr,sizeof(serv_addr)) < 0){ perror("sendto"); exit(1); } } /*打印主菜单*/ void show_opt(void) { msg),0,(struct sockaddr printf("《A:@私聊模式》\t《B:@群聊模式》\n《C:@上传文件》\t《D:@下载文 件》\n《E:@刷新列表》\t《F:@下线离开》\n"); printf("请选择(如:A):\n"); } /*接收消息函数,接收各种由服务器发来的数据,根据数据类型分别处理*/ void *recv_chat_func() { int ret = -1; int i = 0; struct msg rcv_buf; char quick_repeat[] = "亲,我有点事离开,稍后联系!"; while(1){ bzero(&rcv_buf,sizeof(rcv_buf)); ret = recvfrom(cli_fd,&rcv_buf,sizeof(rcv_buf),0,NULL,NULL); if(ret < 0){ perror("recvfrom"); exit(1); } printf("接收到消息,消息类型:%d\n 内容:%s\n",rcv_buf.type,rcv_buf.data); rcv_buf.data[ret - // // sizeof(rcv_buf.type)-sizeof(rcv_buf.self_name)-sizeof(rcv_buf.dst_name)] = '\0'; /*登录消息,刷新消息*/ if(rcv_buf.type == LOG_IN || rcv_buf.type == REFRESH){ printf("@%s\t",rcv_buf.data); fflush(NULL); } /*发送结束消息*/ else if(rcv_buf.type == OVER){ 3
局域网通信软件——by liaoye928 printf("\n"); } /*用户名重复提示消息*/ else if(rcv_buf.type == ERROR){ printf("登录失败!\n"); printf("%s",rcv_buf.data); exit(1); } /*下载时文件不存在提示消息*/ else if(rcv_buf.type == FILE_ERROR){ printf("<文件传输>提示信息:%s\n",rcv_buf.data); pthread_cancel(tid4); //如若输入文件名出错,取消线程,退出监听 } /*文件名列表消息*/ else if(rcv_buf.type == FILE_NAME){ printf("<%s>\t\t",rcv_buf.data); i++; if(i%4 == 0){ printf("\n"); } fflush(NULL); } /*正常聊天消息(私聊)*/ else { printf("新消息!===消息来自《%s》:\n",rcv_buf.self_name); printf("--------------------------\n"); printf("消息内容:%s",rcv_buf.data); printf("( 若 要 与 %s 聊 天 , 请 退 回 主 界 面 重 新 选 择 私 聊 对 象。)\n\n",rcv_buf.self_name); } } } /*私聊函数,参数均为全局变量*/ void chat_private(void) { char peer_name[20]; char chat_data[MAXSIZE]; bzero(&chat_data,sizeof(chat_data)); bzero(&peer_name,sizeof(peer_name)); printf("请选择聊天对象:\n"); scanf("%s",peer_name); 4
局域网通信软件——by liaoye928 while(getchar() != '\n'); //usleep(100000);//延时下 printf("-----------------正在与《%s》聊天-------------------\n",peer_name); while(1){ printf("请输入聊天内容(按回车键发送):\n"); printf("-----输入 quit 退回主界面-----\n"); fgets(chat_data,sizeof(chat_data),stdin); if(strncmp(chat_data,"quit",4) == 0) break; send_sig(myname,peer_name,chat_data,serv_addr,CHAT_PRI); printf("--------------------\n"); } } /*线程:接收群聊消息(广播)*/ void *chat_toall_recv() { int ret = -1; int num = -1; sock_fd = cli_fd; // struct msg rcv_buf; /*获取本机 IP 并分配一个端口*/ struct hostent *h_info; struct in_addr **p_addr; h_info = gethostbyname("ubuntu"); p_addr = ((struct in_addr **)(h_info->h_addr_list)); struct sockaddr_in self_addr; memset(&self_addr,0,sizeof(self_addr)); self_addr.sin_family = AF_INET; self_addr.sin_port = htons(17891); self_addr.sin_addr.s_addr = htonl(INADDR_ANY); struct ip_mreq group; bzero(&group,sizeof(group)); group.imr_multiaddr.s_addr = inet_addr("224.100.100.100"); group.imr_interface = *(*p_addr); /*允许地址重用*/ ret = setsockopt(sock_fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&group,sizeof(group)); if(ret < 0){ perror("setsockopt to ADD_MEMBERSHIP"); 5
- 局域网通信软件——by liaoye928 exit(1); } ret = bind(sock_fd,(struct sockaddr *)&self_addr, sizeof(self_addr)); if(ret < 0){ perror("bind"); exit(1); } while(1){ //printf("等待接收群聊消息\n"); ret = recvfrom(sock_fd,&rcv_buf,sizeof(rcv_buf),0,NULL,NULL); //printf("新的群聊消息\n"); if(ret < 0){ perror("recvfrom"); exit(1); } rcv_buf.data[ret sizeof(rcv_buf.type)-sizeof(rcv_buf.self_name)-sizeof(rcv_buf.dst_name)] = '\0'; printf("=====《群聊》消息来自<%s>:\n",rcv_buf.self_name); printf("--------------------------\n"); printf("消息内容:%s",rcv_buf.data); } } /*发送群聊消息,其实跟饲料消息基本一样的,消息类型不一样而已*/ void chat_toall(void) { char chat_data[MAXSIZE]; bzero(&chat_data,sizeof(chat_data)); printf("--------------------------------------------------------\n"); printf("---------------<正在与所有在线用户聊天>-----------------\n"); while(getchar() != '\n'); while(1){ printf("请输入聊天(群聊)内容(按回车键发送):\n"); printf("-----输入 quit 退回主界面-----\n"); fgets(chat_data,sizeof(chat_data),stdin); if(strncmp(chat_data,"quit",4) == 0) break; send_sig(myname,NULL,chat_data,serv_addr,CHAT_ALL); } } 6
局域网通信软件——by liaoye928 /*线程:接收文件*/ void *recv_file(void *file_name) { char download_path[80] = "/home/file_download/"; int file_fd = -1; int recv_fd = -1; int new_fd = -1; int ret = -1; int num = -1; char buf[BUFSIZ]; struct sockaddr_in file_addr; //printf("文件名:%s\n",(char *)file_name); strcat(download_path,(char *)file_name); file_fd = open(download_path, O_WRONLY|O_CREAT,0666); if(file_fd < 0){ perror("open"); pthread_exit(NULL); } recv_fd = socket(AF_INET,SOCK_STREAM,0); if (recv_fd < 0){ perror("socket"); pthread_exit(NULL); } int on = 1; ret = setsockopt(recv_fd,SOL_SOCKET,SO_REUSEADDR,(void *)&on,sizeof(on)); if(ret < 0){ perror("setsockopt to SO_REUSEADDR"); pthread_exit(NULL); } struct hostent *h_info; struct in_addr **p_addr; h_info = gethostbyname("ubuntu"); p_addr = ((struct in_addr **)(h_info->h_addr_list)); bzero(&file_addr,sizeof(struct sockaddr)); file_addr.sin_family = AF_INET; file_addr.sin_port = htons(12345); file_addr.sin_addr = *(*p_addr); //printf("\n 下 7 至 :%s(%d)\n",inet_ntoa(file_addr.sin_addr),ntohs(file_addr.sin_port)); 载 数 addr 据 地 址
局域网通信软件——by liaoye928 ret = bind(recv_fd,(struct sockaddr *)&file_addr, sizeof(struct sockaddr)); if(ret < 0){ perror("bind"); pthread_exit(NULL); } ret = listen(recv_fd,8); if(ret < 0){ perror("listen"); pthread_exit(NULL); } new_fd = accept(recv_fd,NULL,NULL); while(1){ bzero(&buf,sizeof(buf)); ret = read(new_fd,buf,sizeof(buf)); if(ret < 0){ perror("read"); pthread_exit(NULL); } if(ret == 0){ break; } if(ret > 0){ num = write(file_fd,buf,ret); if(num < 0){ perror("write"); pthread_exit(NULL); } } } printf("<%s>下载完成\n",(char *)file_name); printf("(文件保存路径为:/home/file_download/)\n"); close(file_fd); close(recv_fd); close(new_fd); pthread_exit(NULL); } /*发出下载请求并创建接收数据线程*/ void download(void) { 8
分享到:
收藏