linux系统 局域网通信软件.docx
- 文档编号:29034926
- 上传时间:2023-07-20
- 格式:DOCX
- 页数:43
- 大小:60.44KB
linux系统 局域网通信软件.docx
《linux系统 局域网通信软件.docx》由会员分享,可在线阅读,更多相关《linux系统 局域网通信软件.docx(43页珍藏版)》请在冰豆网上搜索。
linux系统局域网通信软件
/************************************************************
功能
A,私聊B,群聊,C,从服务器下载文件D,上传文件到服务器,E,用户上下线通知,F,刷新在线用户列表,E,下线
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
#defineMAXSIZE512
/*服务器接收消息后,创建的在线用户列表*/
structuser_info{
charuser_name[20];
intid;
structsockaddr_incli_addr;
structuser_info*next;
};
/*客户端给服务器发送的消息*/
structmsg{
chartype;
charself_name[20];
chardst_name[20];
chardata[MAXSIZE];
};
/*消息类型定义*/
enummsg_type{
LOG_IN=1,//登录
REFRESH,//要求刷新用户在线用户(重新打印在线用户)
CHAT_PRI,//私聊消息
CHAT_ALL,//群聊消息
DOWNLOAD,//从服务器下载文件(下载之前先打印文件列表)
UPLOAD,//上传文件到服务器
OFFLINE,//下线通知
OVER,//服务器发送本次消息结束
ERROR,//重复登录
FILE_NAME,//发送文件列表
FILE_ERROR//选择文件名失败
};
/*服务器总列表*/
structservmsg
{
structmsgrecvmsg;
structsockaddr_inaddr;
structservmsg*next;
};
/*客户端源程序--liaoye928*/
#include"include.h"
staticintcli_fd=-1;//主要套接字,用于接受服务器各种消息
staticintsock_fd=-1;//组播套接字,用于群聊
staticstructsockaddr_inserv_addr;//用于存储服务器IP和端口
staticcharmyname[20];//用于存储用户名
staticpthread_ttid4=-1;//将其定义为全局变量的原因是,接收线程会将其取消
/*创建数据报套接字函数*/
intudp_link(void)
{
intsock_fd;
sock_fd=socket(AF_INET,SOCK_DGRAM,0);
returnsock_fd;
}
/*用于给服务其发送数据的函数*/
voidsend_sig(charmyname[],chardesname[],chardata[],structsockaddr_inserv_addr,charch)
{
structmsgmymsg;
mymsg.type=ch;
if(myname!
=NULL)
strcpy(mymsg.self_name,myname);
if(desname!
=NULL)
strcpy(mymsg.dst_name,desname);
if(data!
=NULL)
strcpy(mymsg.data,data);
if(sendto(cli_fd,&mymsg,sizeof(structmsg),0,(structsockaddr*)&serv_addr,sizeof(serv_addr))<0){
perror("sendto");
exit
(1);
}
}
/*打印主菜单*/
voidshow_opt(void)
{
printf("《A:
@私聊模式》\t《B:
@群聊模式》\n《C:
@上传文件》\t《D:
@下载文件》\n《E:
@刷新列表》\t《F:
@下线离开》\n");
printf("请选择(如:
A):
\n");
}
/*接收消息函数,接收各种由服务器发来的数据,根据数据类型分别处理*/
void*recv_chat_func()
{
intret=-1;
inti=0;
structmsgrcv_buf;
//charquick_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);
}
/*发送结束消息*/
elseif(rcv_buf.type==OVER){
printf("\n");
}
/*用户名重复提示消息*/
elseif(rcv_buf.type==ERROR){
printf("登录失败!
\n");
printf("%s",rcv_buf.data);
exit
(1);
}
/*下载时文件不存在提示消息*/
elseif(rcv_buf.type==FILE_ERROR){
printf("<文件传输>提示信息:
%s\n",rcv_buf.data);
pthread_cancel(tid4);//如若输入文件名出错,取消线程,退出监听
}
/*文件名列表消息*/
elseif(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);
}
}
}
/*私聊函数,参数均为全局变量*/
voidchat_private(void)
{
charpeer_name[20];
charchat_data[MAXSIZE];
bzero(&chat_data,sizeof(chat_data));
bzero(&peer_name,sizeof(peer_name));
printf("请选择聊天对象:
\n");
scanf("%s",peer_name);
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()
{
intret=-1;
intnum=-1;
//sock_fd=cli_fd;
structmsgrcv_buf;
/*获取本机IP并分配一个端口*/
structhostent*h_info;
structin_addr**p_addr;
h_info=gethostbyname("ubuntu");
p_addr=((structin_addr**)(h_info->h_addr_list));
structsockaddr_inself_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);
structip_mreqgroup;
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("setsockopttoADD_MEMBERSHIP");
exit
(1);
}
ret=bind(sock_fd,(structsockaddr*)&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);
}
}
/*发送群聊消息,其实跟饲料消息基本一样的,消息类型不一样而已*/
voidchat_toall(void)
{
charchat_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);
}
}
/*线程:
接收文件*/
void*recv_file(void*file_name)
{
chardownload_path[80]="/home/file_download/";
intfile_fd=-1;
intrecv_fd=-1;
intnew_fd=-1;
intret=-1;
intnum=-1;
charbuf[BUFSIZ];
structsockaddr_infile_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);
}
inton=1;
ret=setsockopt(recv_fd,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
if(ret<0){
perror("setsockopttoSO_REUSEADDR");
pthread_exit(NULL);
}
structhostent*h_info;
structin_addr**p_addr;
h_info=gethostbyname("ubuntu");
p_addr=((structin_addr**)(h_info->h_addr_list));
bzero(&file_addr,sizeof(structsockaddr));
file_addr.sin_family=AF_INET;
file_addr.sin_port=htons(12345);
file_addr.sin_addr=*(*p_addr);
//printf("\n下载数据至地址addr:
%s(%d)\n",inet_ntoa(file_addr.sin_addr),ntohs(file_addr.sin_port));
ret=bind(recv_fd,(structsockaddr*)&file_addr,sizeof(structsockaddr));
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);
}
/*发出下载请求并创建接收数据线程*/
voiddownload(void)
{
charfile_name[64];
printf("当前资源中心所有文件:
\n");
usleep(100000);
/*此次接收文件列表*/
printf("\n请选择一个文件下载:
\n");
scanf("%s",file_name);
send_sig(myname,NULL,file_name,serv_addr,DOWNLOAD);
if(pthread_create(&tid4,NULL,recv_file,(void*)file_name)){
perror("pthread_create2");
exit
(1);
}
pthread_join(tid4,NULL);
}
/*发送文件*/
void*send_file(void*file_name)
{
intfile_fd=-1;
intsend_fd=-1;
charbuf[BUFSIZ];
intret=-1;
intnum=-1;
intlen=-1;
structsockaddr_infile_addr;
charfile_path[80]="/home/file_centre/";
strcat(file_path,(char*)file_name);
file_fd=open(file_path,O_RDONLY);
if(file_fd<0){
perror("open");
printf("对不起,您选择有误!
请重新进入上传模式。
\n");
pthread_exit(NULL);
}
send_fd=socket(AF_INET,SOCK_STREAM,0);
if(send_fd<0){
perror("socket");
pthread_exit(NULL);
}
structhostent*h_info;
structin_addr**p_addr;
h_info=gethostbyname("ubuntu");
p_addr=((structin_addr**)(h_info->h_addr_list));
bzero(&file_addr,sizeof(structsockaddr));
file_addr.sin_family=AF_INET;
file_addr.sin_port=htons(54321);
file_addr.sin_addr=*(*p_addr);
usleep(200000);
ret=connect(send_fd,(structsockaddr*)&file_addr,sizeof(structsockaddr_in));
if(ret<0){
perror("connect");
pthread_exit(NULL);
}
len=lseek(file_fd,0L,SEEK_END);
lseek(file_fd,0L,SEEK_SET);
while(len>0){
bzero(&buf,sizeof(buf));
ret=read(file_fd,buf,sizeof(buf));
if(ret<0){
perror("read");
pthread_exit(NULL);
}
num=write(send_fd,buf,ret);
if(num<0){
perror("write");
pthread_exit(NULL);
}
}
printf("文件上传成功!
\n");
pthread_exit(NULL);
}
/*下载文件*/
voidupload(void)
{
chardownload_path[80]="/home/liaoye/file_download/";
charfil
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- linux系统 局域网通信软件 linux 系统 局域网 通信 软件