小目标7 上传文件功能
客户端和服务器都增加上传文件的宏定义
#define MSG_TYPE_UPLOAD 3
修改客户端case3的部分
up_file_name是要上传的文件名
char up_file_name[20] = { 0 };//定义为全局变量
//下面是修改后客户端的代码
case '3':
send_msg.type = MSG_TYPE_UPLOAD;
printf("input upload filename:");
puts(up_file_name);
//在上传文件给服务器之前,你要先发送一个数据包给服务器,告诉服务器我这边准备上传文件了
strcpy(send_msg.fname, up_file_name);
res = write(client_socket, &send_msg, sizeof(MSG));
if (res < 0)
{
perror("send upload package error:");
continue;
}
memset(&send_msg, 0, sizeof(MSG));
服务器部分的线程函数要增加一个判断,如果type是上传,就读从客户端发来的数据,然后创建文件夹
也要定义:char up_file_name[20]
else if (recv_msg.type == MSG_TYPE_UPLOAD) //如果收到的是上传包,说明准备接收客户端发来的文件数据了
{
//要从数据包的文件名里面获取文件名信息,然后创建文件。默认创建的文件夹是在家目录下
strcpy(up_file_name, recv_msg.fname);
//然后在家目录下创建文件
fd = open("/home/liujiajun/css.txt", O_CREAT | O_WRONLY, 0666);
if (fd < 0)
{
perror("create up file error:");
}
}
客户端因为发送文件需要比较长的时间,如果在case3里面写传输文件的代码就可能会寄,所以我们再创建一个新的线程来专门处理文件上传任务,然后在客户端里面写一个上传文件的线程函数。修改后的代码如下
//上传文件函数
void* upload_file_thread(void* arg) {
}
//case3部分:
case '3':
send_msg.type = MSG_TYPE_UPLOAD;
printf("input upload filename:");
puts(up_file_name);
//在上传文件给服务器之前,你要先发送一个数据包给服务器,告诉服务器我这边准备上传文件了
strcpy(send_msg.fname, up_file_name);
res = write(client_socket, &send_msg, sizeof(MSG));
if (res < 0)
{
perror("send upload package error:");
continue;
}
memset(&send_msg, 0, sizeof(MSG));
pthread_create(&thread_send_id, NULL, upload_file_thread, &client_socket);
break;
//由于考虑到上传文件是需要比较长的时间,考虑到如果文件很大,那么就需要非常长的时间,这个时候如果写
// //在这里那么久卡诺导致其他功能卡住排队等待,因此需要把发送文件内容的代码放进线程里面,因此需要创建线程
// //还需要创建一个新的线程,来专门处理文件上传任务
当前代码执行后在Ubantu的主目录下会多一个名为css.txt的文件,说明服务器创建文件成功
真正上传数据的时候还需要一个宏定义(服务器和客户端都要)
#define MSG_TYPE_UPLOAD_DATA 4
接下来我们开始写客户端上传文件的线程函数
void* upload_file_thread(void* args)
{
// 客户端实现长传文件到服务器的逻辑思路
//1 肯定是要打开文件
MSG up_file_msg = { 0 };
char buffer[1024] = { 0 }; // 用来保存读取文件的数据缓冲区
int client_socket = *((int*)args);
int res = 0;
int fd = -1;
fd = open("./download/css/txt", O_RDONLY);
if (fd < 0)
{
perror("open up file error : ");
return NULL;
}
up_file_msg.type = MSG_TYPE_UPLOAD_DATA;
while ((res = read(fd, buffer, sizeof(buffer))) > 0)
{
// 要把文件数据内容拷贝到 MSG 结构体中的 buffer 中
memcpy(up_file_msg.buffer, buffer, res);
up_file_msg.bytes = res;
res = write(client_socket, &up_file_msg, sizeof(MSG));
memset(buffer, 0, sizeof(buffer));
memset(up_file_msg.buffer, 0, sizeof(up_file_msg.buffer));
}
close(fd);
}
然后再服务器的线程函数里面再加一个判断
else if (recv_msg.type == MSG_TYPE_UPLOAD_DATA)
{
//写的字节数是recv_msg.bytes
write(fd, recv_msg.buffer, recv_msg.bytes);
if (recv_msg.bytes < sizeof(recv_msg.buffer))
{
printf("client uploaded file: %s\n", up_file_name);
close(fd);
}
memset(&recv_msg, 0, sizeof(MSG));
}