⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 client.cpp

📁 linux网络程序设计 几个小程序以及编译命令
💻 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 + -