客户端与服务器项目3

客户端与服务器项目3,第1张

客户端与服务器项目3 10、客户端主要程序

1、传输文件时读取标准输入:暂停、停止

void *thread_function(void)
{
	fd_set m_fdset;						//待检查文件的描述符
	struct timeval timeout = {1, 0};	//设置超时时间为1秒
	//用select超时实现非阻塞读取标准输入
	while(1)
	{
		//select函数不会修改timeout的值,所以每次循环都应该重新赋值
		timeout.tv_sec = 1;
		timeout.tv_usec = 0;
		if(FILE_STATE_START == m_filestate)
		{
			FD_ZERO(&m_fdset);			//清空m_fdset变量
			FD_SET(STDIN_FILENO, &m_fdset);//设置为标准输入
			switch(select(STDIN_FILENO+1, &m_fdset, NULL, NULL, &timeout))
			{
				//出错
				case -1:
				perror("select");
				break;
				//超时
				case 0:
				break;
				//发生状态变化的文件描述符的个数
				default:
				if(FD_ISSET(STDIN_FILENO, &m_fdset))
				{
					char ch = fgetc(stdin);
					//文件传输暂停
					if(FILE_TRANS_PAUSE == atoi(&ch))
					{
						m_filestate = FILE_STATE_PAUSE;
					}
					//文件传输停止
					else if(FILE_TRANS_STOP == atoi(&ch))
					{
						m_filestate = FILE_STATE_STOP;
					}
				}
				break;
			}
		}
		else
		{
			//没有传输文件,线程休眠
			sleep(1);
		}
	}
}
				

2、主函数

int main(int argc, char *argv[])
{
	int sockfd = -1;
	int sockerr = 0;
	int socklen = sizeof(struct sockaddr_in);
	struct sockaddr_in server_addr;
	//文件传输相关
	int retval = 0;			//文件传输返回字节数
	int torecv = 0;			//剩余要接收的文件大小
	char buf[BUFFER_SIZE] = {0};
	FILE *fp = NULL;
	protocol m_protocol;		//协议结构体
	server_config m_config;		//服务器配置结构体
	file_info m_fileinfo;		//传输文件信息结构体
	memset(&m_fileinfo, 0, sizeof(file_info));
	pthread_t thread_handle = 0; //线程句柄
	//创建一个线程在文件传输时接收标准输入
	if(pthread_create(&thread_handle, NULL, (void*)thread_function, NULL) != 0)
	{
		perror("pthread_create");
		return -1;
	}
	//创建一个套接字
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd == -1)
	{
		perror("socket");
		return -1;
	}
	//配置服务器地址与端口
	bzero(&server_addr, sizeof(struct sockaddr_in));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(SOCKET_PORT);
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	//连接服务器
	if(connect(sockfd, (struct sockaddr*)&server_addr, socklen) == -1)
	{
		perror("connect");
		close(sockfd);
		return -1;
	}
	while(!sockerr)
	{
		char ch[100] = {0};
		memset(&m_protocol, 0, sizeof(protocol));
		printf("***********************n"
			   "1:Get file list       *n"
			   "2:Get server config   *n"
			   "3:Set server config   *n"
			   "4:Start file trans    *n"
			   "5:Start file trans    *n"
			   "6:Start file trans    *n"
			   "***********************n");
		printf("Please input command:");
		scanf("%s", ch);
		m_protocol.cmd = ch[0] - '0';
		//对异常输入进行判断
		if(m_protocol.cmd < 1 || m_protocol.cmd > 6 || ch[1] != 0)
		{
			printf("The command is invalid!n");
		}
		else
		{
			switch(m_protocol.cmd)
			{
				//获取文件列表
				case GET_FILE_LIST:
				if(-1 == write(sockfd, (char*)&m_protocol, sizeof(protocol)))
				{
					perror("write");
					sockerr = 1;
				}
				memset(buf, 0, BUFFER_SIZE);
				//当socket链接中断时会返回0,read错误时返回-1
				if(read(sockfd, buf, BUFFER_SIZE) <= 0)
				{
					perror("read");
					sockerr = 1;
					break;
				}
				else
				{
					printf("%s", buf);
				}
				break;
				//获取服务器配置参数
				case GET_SER_CONFIG:
				if(-1 == write(sockfd, (char*)&m_protocol, sizeof(protocol)))
				{
					perror("write");
					sockerr = 1;
				}
				memset(&m_config, 0, sizeof(server_config));
				//当socket链接中断时会返回0,read错误时返回-1
				if(read(sockfd, (char*)&m_config, sizeof(server_config)) <= 0)
				{
					perror("read");
					sockerr = 1;
					break;
				}
				else
				{
					printf("name:%sclient_max:%dn", m_config.name, m_config.clieng_max);
				}
				break;
				//设置服务器配置参数
				case SET_SER_CONFIG:
				printf("Please input server name:");
				scanf("%s", m_protocol.name);
				printf("Please input the max number of server:");
				scanf("%d", &m_protocol.length);
				if(-1 == write(sockfd, (char*)&m_protocol, sizeof(protocol)))
				{
					perror("write");
					sockerr = 1;
				}
				//获取服务器配置的结果
				if(read(sockfd, (char*)&m_config, sizeof(server_config)) <= 0)
				{
					perror("read");
					sockerr = 1;
				}
				else
				{
					if(!xtrcmp(m_protocol.name, "")
					{
						printf("Set server config failed!");
					}
					else
					{
						printf("Set server config success!n");
						printf("name:%snclient_max:%dn", m_config.name, m_config.client_max);
					}
				}
				break;
				//文件开始传输
				case FILE_TRANS_START:
				if(torecv > 0)
				{
					strncpy(m_protocol.name, m_fileinfo.name, NAME_LEN);
					printf("FILE name:%sn", m_protocol.name);
				}
				else
				{
					printf("Please input file name:");
					scanf("%s", m_protocol.name);
				}
				if(-1 == write(sockfd, (char*)&m_protocol, sizeof(protocol)))
				{
					perror("write");
					sockerr = 1;
				}
				//接收服务器的回复,判断是否满足文件传输的条件
				memset(&m_protocol, 0, sizeof(protocol));
				if(read(sockfd, (char*)&m_protocol, sizeof(protocol)) <= 0)
				{
					perror("read");
					sockerr = 1;
				}
				else
				{
					if(strcmp(m_protocol.name, "") != 0)
					{
						if(torecv > 0)
						{
							//继续传输旧文件,以附加的方式打开只写文件
							fp = fopen(m_protocol.name, "a")
						}
						else
						{
							//传输新文件
							torecv = m_protocol.length;
							fp = fopen(m_protocol.name, "w");
						}
						if(NILL == fp)
						{
							perror("fopen");
						}
						else
						{
							printf("Start receiving file!n");
							m_filestate = FILE_STATE_START;
							while((retval = read(sockfd, buf, sizeof(buf))) > 0)
							{
								fwrite(buf, 1, retval, fp);
								memset(buf, 0, sizeof(buf));
								//计算剩余字节数
								torecv -= retval;
								if(torecv <= 0)
								{
									printf("FILE:%s receive success!n", m_protocol.name);
								//清除文件信息
								torecv = 0;
								memset(&m_fileinfo, 0, sizeof(file_info));
								m_filestate = FILE_STATE_STOP;
								if(write(sockfd, (char*)&m_protocol, sizeof(protocol)) < 0)
								{
									perror("write");
									sockerr = 1;
								}
								break;
								else
								{
									//暂停传输
									if(FILE_STATE_PAUSE == filestate)
									{
										strncpy(m_fileinfo.name, m_protocol.name, NAME_LEN);
									printf("FILE_TRANS_PAUSE!n"
											"Left:%dn", torecv);
									//发送暂停命令
									memset(&M-protocol, 0, sizeof(protocol));
									m_protocol.cmd = FILE_TRANS_PAUSE;
									if(write(sockfd, (char*)&m_protocol, sizeof(protocol)) < 0)
									{
										perror("write");
										sockerr = 1;
									}
									break;
									}
									//停止传输
									else if(FILE_STATE_STOP == m_filestate)
									{
										torecv = 0;
										memset(&m_fileinfo, 0, sizeof(file_info));
										printf("FILE_TRANS_STOP!n");
										//发送停止命令
										m_protocol.cmd = FILE_TRANS_STOP;
										if(write(sockfd, (char*)&m_protocol, sizeof(protocol)) < 0)
										{
											perror("write");
											sockerr = 1;
										}
										break;
										}
									else
									{
										if(write(sockfd, (char*)&m_protocol, sizeof(protocol)) < 0)
										{
											perror("write");
											sockerr = 1;
										}
									}
								}
							}
							fclose(fp);
							fp = NULL;
						}
					}
					else
					{
						printf("File not exist!n");
					}
				}
				break;
				//文件暂停传输
				case FILE_TRANS_PAUSE:
				//指令在线程中读取
				if(m_filestate != FILE_STATE_START)
				{
					printf("No file is transferring!n");
				}
				break;
				//文件停止传输
				case FILE_TRANS_STOP:
				//指令在线程中读取
				if(m_filestate != FILE_STATE_START)
				{
					printf("No fole is transferring!n");
				}
				break;
				default:
				break;
				}
			}
		}
		close(sockfd);
		return 0;
	}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4664851.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-07
下一篇 2022-11-06

发表评论

登录后才能评论

评论列表(0条)

保存