📄 client.cpp
字号:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <setjmp.h>
#include <string.h>
#include <sys/time.h>
#define DEFAULT_PORT 7000
#define DEFAULT_BUFFER_SIZE 4096
//参数解析函数
//参数1指定服务器
//参数2指定本地文件路径
void validateArgs(int argc,char **args);
//由文件路径获得文件名
void getFileName(char *filepath,char *filename);
//数据传送函数
void transData(int sClient,FILE *fp);
char *szServName;
char *szFilePath;
//入口函数
main(int argc,char **args)
{
FILE *fp;
printf("\n***** Fileput Client *****\n");
printf("Starting...\n");
//接收服务器名,文件路径
validateArgs(argc,args);
//试图打开文件
printf("Loading file...\n");
fp=fopen(szFilePath,"rb");
if(fp==NULL)
{
printf("Can not open file.\n");
return 1;
}
printf("File opened.\n");
int sClient;
struct sockaddr_in server;
//建立套接字
sClient=socket(AF_INET,SOCK_STREAM,0);
if(sClient==-1)
{
printf("socket() failed\n");
return 1;
}
//解析服务器名
struct hostent *host=NULL;
host=gethostbyname(szServName);
if(host==NULL)
{
printf("Unable to resolve server: %s\n",szServName);
return 1;
}
memcpy(&server.sin_addr,host->h_addr_list[0],host->h_length);
server.sin_family=AF_INET;
server.sin_port=htons(DEFAULT_PORT);
//连接服务器
if(connect(sClient,(struct sockaddr *)&server,
sizeof(server))==-1)
{
printf("connect() failed\n");
return 1;
}
printf("Connection established to %s [%s]\n",host->h_name,
inet_ntoa(server.sin_addr)/*inet_ntoa(
*((in_addr *)host->h_addr_list[0])
)*/);
//进行数据传送
transData(sClient,fp);
close(sClient);
printf("Socket closed.\n");
fclose(fp);
printf("File closed.\n");
return 0;
}
void validateArgs(int argc,char **args)
{
switch(argc)
{
case 3:
szServName=args[1];
szFilePath=args[2];
break;
default:
printf("Invalid arguments.\n");
exit(1);
break;
}
}
void transData(int sock,FILE *fp)
{
char *rcvbuff=new char[DEFAULT_BUFFER_SIZE];
char *sndbuff=new char[DEFAULT_BUFFER_SIZE];
//设置send/recv超时
struct timeval timeout={2,0};
int bread=setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,
(char *)&timeout,sizeof(timeout));
if(bread==-1)
{
printf("setsockopt(SO_RCVTIMEO) failed\n");
return;
}
bread=setsockopt(sock,SOL_SOCKET,SO_SNDTIMEO,
(char *)&timeout,sizeof(timeout));
if(bread==-1)
{
printf("setsockopt(SO_SNDTIMEO) failed\n");
return;
}
//等待服务器欢迎信息"hello"
printf("Waiting for Greeting message...\n");
read(sock,rcvbuff,DEFAULT_BUFFER_SIZE);
if(strcmp(rcvbuff,"hello"))
{
printf("Invalid greeting message:%s\n",rcvbuff);
return;
}
do
{
//获取文件名
char *szFileName=new char[100];
getFileName(szFilePath,szFileName);
printf("File name: %s\n",szFileName);
//获取文件大小
fseek(fp,0,SEEK_END);
long flen=ftell(fp);
printf("File size: %d\n",flen);
//构造文件信息消息
//格式:"info",szFilename,flen
//"info"长度5,szFilename长度namelen+1,flen长度4
//总长度10+namelen
int namelen=strlen(szFileName);
int infomsg_len=10+namelen;
char *infomsg=new char[infomsg_len];
memcpy(infomsg,"info",5);
memcpy(infomsg+5,szFileName,namelen+1);
memcpy(infomsg+5+namelen+1,&flen,4);
//向服务器发送文件信息
write(sock,infomsg,infomsg_len);
//等待服务器就绪信息"ready"
read(sock,rcvbuff,DEFAULT_BUFFER_SIZE);
if(strcmp(rcvbuff,"ready"))
{
printf("Server not ready:%s\n",rcvbuff);
break;
}
printf("Server is ready.\nUploading...\n");
//开始传送数据
rewind(fp);
//数据格式:"data",index,[文件内容]
memcpy(sndbuff,"data",5);
int ret;
int index=0;//当前传送数据块在文件中的偏移量
while(true)
{
ret=fread(sndbuff+9,sizeof(char),DEFAULT_BUFFER_SIZE-9,fp);
if(ret<=0)
{
break;
}
memcpy(sndbuff+5,&index,4);
printf("send --- %d: ",index);
index+=ret;
ret=write(sock,sndbuff,ret+9);
printf("%dbytes\n",ret-9);
}
printf("File upload complete.\n");
}
while(false);
sleep(1);//避免"bye"和上一个文件块一起接收
//发送结束信息
write(sock,"bye",4);
}
void getFileName(char *filepath,char *filename)
{
int pathlen=strlen(filepath);
char *p=filepath+pathlen;
while((*p!=':')&&(*p!='\\')&&(*p!='/')&&(p>=filepath))
{p--;}
//p最终指向文件名前一个字节
memcpy(filename,p+1,filepath+pathlen-p);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -