c语言linux编程进阶,linux c语言高级编程-网络编程进阶

//协义头 protocol.h

#ifndef PROTOCOL_H

#define PROTOCOL_H

//定义错误号

#define ERR_CHECKNUM 00000001//校验错误

#define ERR_GETFILE_NOTHING 00000002//没有要获取的文件

//定义宏指令

#define REQ_CMD_GETFILELS 000000001//获取文件列表请求

#define REV_CMD_GETFILELS 000010001//获取文件列表应答

#define REQ_CMD_GETFILE 000000002//获取文件

#define REV_CMD_GETFILE 000010002//获取文件

//定义协议头

typedef struct HEAD{

int id; //代表本次发送数据的编号

int cmd; //指令

int len; //总长

int size;//本次长度

int err; //错误号 0为正确,非零为错误

int cknum;//校验码

} head_t;

//定义发送的数据

//1. 获取文件列表请求

struct REQFILELS{

char dirname[256]; //请求列表时,可指定目录名

};

//2. 获取列表的应答

//发送的数据为 char数组类型,长度在head中指定。文件名与文件名之间用 "|"分隔

//3.获取文件请求

struct REQFILE{

char filename[256]; //请求时,必须指定要下载的包含目录的文件名

};

//4.获取文件应答

//发送文件数据,本次发送的长度,记录在head中,当累计长度>=总长,代表发送完毕

struct REVFILE{

char filename[256];

char data[2048];

};

#endif

//read.c 客户端

#include

#include

#include

#include

#include

#include "libsock/libcli.h"

#include "protocol.h"

char sendbuf[4096];

//校验码

unsigned short cal_chksum(char *addr,int len){

int nleft=len;

int sum=0;

unsigned short *w=(unsigned short*)addr;

unsigned short answer=0;

//把ICMP报头二进制数据以2字节为单位累加起来

while(nleft>1){

sum+=*w++;

nleft-=2;

}

//若ICMP报头为奇数个字节,会剩下最后一字节。把最后一个字节视为一个2字节数据的高字节,这个2字节数据的低字节为0,继续累加

if( nleft==1){

*(unsigned char *)(&answer)=*(unsigned char *)w;

sum+=answer;

}

sum=(sum>>16)+(sum&0xffff);

sum+=(sum>>16);

answer=~sum;

return answer;

}

//回调,用来接收数据

int recvdata(char *buf,int size){

struct HEAD *head=(struct HEAD*)buf;

//先校验数据

/*

int cknum=head->cknum;

head->cknum=0;

if (cal_chksum(buf,sizeof(struct HEAD)+head->size)!=cknum){

//接收数据有误,装载协议头

head->cmd=head->cmd | 00010000;

head->err=ERR_CHECKNUM;

head->cknum=cal_chksum(buf,sizeof(struct HEAD));

clidev.send(buf,sizeof(struct HEAD));

return -1;

}

*/

printf("----------------------------- recv \n");

//解析协议

switch(head->cmd){

case REV_CMD_GETFILELS: //客户端的应答 要文件列表

{

char *data=buf+sizeof(struct HEAD);

char *result=strtok(data,"|");

while(result != NULL ){

printf("%s\n",result);

result=strtok(NULL,"|");

}

}

break;

case REV_CMD_GETFILE: //客户端的应答 要文件

{

static int allsize=0;

static fd=0;

char *filename=buf+sizeof(struct HEAD);

//打开文件

if (allsize==0){

printf("--------- file 1\n");

fd=open(filename,O_CREAT | O_RDWR);

}

if (fd==-1) return -1;

printf("--------- file 2\n");

//保存数据

write(fd,buf+sizeof(struct HEAD)+256,head->size-256);

allsize+=head->size-256;

//关闭文件

if(allsize>=head->len){

printf("--------- file 3\n");

close(fd);

fd=0;

allsize=0;

}

}

break;

}

}

int main(int argc,char **argv){

int i=0;

//启动服务

int err=clidev.start(argv[1],atoi(argv[2]),recvdata);

if (err==-1) return -1;

char buf[256];

while(1){

scanf("%s",buf);

if (strcmp(buf,"l")==0) {

printf("input list dir:\n");

scanf("%s",buf);

//装载协议头

struct HEAD *head=(struct HEAD*)sendbuf;

head->id=i++;

head->cmd=REQ_CMD_GETFILELS;

head->len=256;

head->size=256;

head->err=0;

head->cknum=0;

//装载数据

char *data=sendbuf+sizeof(struct HEAD);

strcpy(data,buf);//指定要获取当前目录文件列表

printf("----dir =%s\n",data);

//校验码

head->cknum=cal_chksum(sendbuf,sizeof(struct HEAD)+head->size);

//发送

clidev.send(sendbuf,sizeof(struct HEAD)+head->size);

}

else if (strcmp(buf,"f")==0){

printf("input filename:\n");

scanf("%s",buf);

//装载协议头

struct HEAD *head=(struct HEAD*)sendbuf;

head->id=i++;

head->cmd=REQ_CMD_GETFILE;

head->len=256;

head->size=256;

head->err=0;

head->cknum=0;

//装载数据

char *data=sendbuf+sizeof(struct HEAD);

strcpy(data,buf);//指定要获取当前目录文件

//校验码

head->cknum=cal_chksum(sendbuf,sizeof(struct HEAD)+head->size);

//发送

clidev.send(sendbuf,sizeof(struct HEAD)+head->size);

}

else if (strcmp(buf,"q")==0) break; //关闭窗口

}

}

//write.c 服务端

#include

#include

#include

#include "libsock/libsev.h"

#include "protocol.h"

unsigned short cal_chksum(char *addr,int len){

int nleft=len;

int sum=0;

unsigned short *w=(unsigned short*)addr;

unsigned short answer=0;

//把ICMP报头二进制数据以2字节为单位累加起来

while(nleft>1){

sum+=*w++;

nleft-=2;

}

//若ICMP报头为奇数个字节,会剩下最后一字节。把最后一个字节视为一个2字节数据的高字节,这个2字节数据的低字节为0,继续累加

if( nleft==1){

*(unsigned char *)(&answer)=*(unsigned char *)w;

sum+=answer;

}

sum=(sum>>16)+(sum&0xffff);

sum+=(sum>>16);

answer=~sum;

return answer;

}

char *getfilels(char *path){

static char ls[4096];

struct stat st;

char pathname[256];

DIR* fp=opendir(path);

if (fp==NULL) return NULL;

struct dirent *db;

int i=0;

while((db=readdir(fp))!=NULL){

if (db->d_name[0]!='.') { //打印文件名或字符串

sprintf(pathname,"%s%s",path,db->d_name);

stat(pathname,&st); //获取文件属性

if (S_ISREG(st.st_mode)){

if (i==0) strcpy(ls,pathname);

else sprintf(ls,"%s|%s",ls,pathname);

i++;

}

}

}

closedir(fp);

if (i==0) return NULL;

else return ls;

}

//回调,用来接收数据

int recvdata(int sockfd,char *buf,int size){

struct HEAD *head=(struct HEAD*)buf;

printf("-------------1\n");

//先校验数据

/*

int cknum=head->cknum;

head->cknum=0;

if (cal_chksum(buf,sizeof(struct HEAD)+head->size)!=cknum){

//接收数据有误

//装载协议头

head->cmd=head->cmd | 00010000;

head->err=ERR_CHECKNUM;

head->cknum=cal_chksum(buf,sizeof(struct HEAD));

sevdev.send(fd,buf,sizeof(struct HEAD));

printf("-------------2\n");

return -1;

}

*/

//解析数据

switch(head->cmd){

case REQ_CMD_GETFILELS: //客户端的请求 要文件列表

{

char *dir=buf+sizeof(struct HEAD);

printf("-------------3 %s\n",dir);

//装载协议头

head->cmd=REV_CMD_GETFILELS;

head->err=0;

char *filels=buf+sizeof(struct HEAD);

strcpy(filels,getfilels(dir));

head->len=strlen(filels);

head->size=strlen(filels);

head->cknum=cal_chksum(buf,sizeof(struct HEAD)+head->size);

//发送数据

sevdev.send(sockfd,buf,sizeof(struct HEAD)+head->size);

}

break;

case REQ_CMD_GETFILE: //客户端的请求 要文件

{

char *filename=buf+sizeof(struct HEAD);

printf("---------- get file 1 %s\n",filename);

int fd1=open(filename,O_RDONLY);

if (fd1==-1){

//发送失败应答

}

else{

printf("---------- get file 2 \n");

int allsize=lseek(fd1,0,2);

lseek(fd1,0,0);

head->cmd=REV_CMD_GETFILE;

head->err=0;

head->len=allsize;

while(allsize>0){

size=allsize%2048;

if (size==0) size=2048;

size=read(fd1,buf+sizeof(struct HEAD)+256,size);

head->size=size+256;

head->cknum=cal_chksum(buf,sizeof(struct HEAD)+size+256);

allsize-=size;

printf("---------- get file 3 %d \n",size);

//发送数据

sevdev.send(sockfd,buf,sizeof(struct HEAD)+256+size);

}

printf("---------- get file 4 \n");

close(fd1);

}

}

break;

}

}

int main(int argc,char **argv){

//启动服务

int err=sevdev.start(atoi(argv[1]),recvdata);

if (err==-1) return -1;

char buf[256];

while(1){

scanf("%s",buf);

if (strcmp(buf,"q")==0) break; //关闭窗口

}

//停止服务

sevdev.stop();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值