项目描述:
使用场景:用于校园,方便学生的日常生活,促进学生交流。
问题描述:设计一个互动平台程序,为学生提供便利,可以在平台上发布和咨询问题,丰富校园文化。
基本要求:
- 实现客户端向服务器发消息。
- 实现客户端从服务器读消息。
- 实现并发服务器,支持多个客户端同时发布或者浏览文章。
- 服务器通过数据库保存发布文章记录(文章标题名称、发布人等)。
- 只支持浏览数据库记录中保存的文章(用户每发布一篇文章,便将文章标题保存在数据库中。浏览文章时,检查数据库中是否存在该文章标题,如果存在才能进入浏览,不存在返回不存在。)
项目模块划分
客户端
菜单界面(后续用Qt界面替换)
- 文章发布:P#文章标题
- 文章浏览:G#文章标题
- 刷新页面:F#文章标题
- 退出:Q
- 删除标题:D#文件名
TCP客户端
- 客户端进行注册用户才能进行操作。
- 客户端注册成功连接到服务器,保持与服务器之间的连接。
- 在客户端界面上输入退出序号4后,断开与服务器的连接并退出。
文章发布
- 拼装协议头,发送给服务器,协议头格式:P#文章保存路径与每一个文章标题名,如:(P#../file/filename)
- 接受服务器消息,进行解析,收到ERROER错误标志则代表该文章已存在数据库中结束发布操作,否则收到SUCCESS成功标志代表可以上传执行下一步。
- 读取待发布的文章路径与文章标题名,将文章的内容发送给服务器,每次发送1024字节,直到读取完毕,此时文章发布完成。
文章浏览
- 拼装协议头,发送给服务器,协议头格式:G#文件路径与文件名。
- 接受服务器消息,进行解析,收到ERROER代表数据库中没有该文章名结束浏览,收到SUCCESS代表可以操作执行下一步。
- 继续接收服务器数据,将接收到的数据写到待下载的文件里,并打印到终端。
服务器
文件上传
- 解析协议头消息,获得命令、文章保存路径、文章标题名。
- 进行判断,查看数据库是否存在该文章命题名,不存在发送ERROR,存在发送SUCCES,并将文章标题名和发布人保存到数据库中,并保存文件名到链表。
- 接收客户端发送的数据,将接收到的数据写到待发布的文章路径里。
文件下载
- 解析协议头消息,进入对应选项并传递路径与文章标题名。
- 从数据库里查询指定文章标题名,如果标题不存在,给客户端发送ERROR,反之存在发送SUCCESS,执行下一步操作。
- 读取待下载的文章名,将文章内容发送给客户端,每次发送1024字节。
支持并发文章发布或者文章浏览
- 服务器接受客户端的连接,为每个客户端分配单独的线程,用于文章发布和浏览。
- 对端关闭套接字时,为该客户端分配的线程退出。
扩展功能:
- 每个用户可以修改文章内容。
- 实现保存功能。
- 更改用户名对应的文章发布人名也发生变动。
项目思路:
设计思路:
- 总体结构:采用TCP编程中的并发服务器结构,并结合数据库与链表进行保存。
- 发布:输入已经编辑好的文章标题,依次输入。
- 浏览:输入存在的标题名,依次浏览。
客户端程序
主程序
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <pthread.h>
//错误标志
#define DOWNLOAD_FILE_ERROR "download_file_error"
//成功标记
#define UPLOAD_FILE_SUCCESS "upload_file_success"
char name[30], key[30], pock[30];
//链表保存文件名和下标
typedef struct name
{
char name[1024];
int nume;
}data_t;
//链表结点
typedef struct Linknode
{
data_t data;
struct Linknode *pNext;
}Linknode;
//链表首地址
typedef struct Link
{
Linknode *pHead;
int count;
}Link;
//保存文件名的结构体
typedef struct save
{
char pock[128];
}Save;
//开辟空间
Link *creat_link()
{
Link *pLink = (Link*)malloc(sizeof(Link));
if(NULL == pLink)
{
return NULL;
}
memset(pLink, 0, sizeof(Link));
return pLink;
}
//创建结点
Linknode *creat_node(data_t tData)
{
Linknode *pNode = (Linknode*)malloc(sizeof(Linknode));
if(NULL == pNode)
{
return NULL;
}
memset(pNode, 0, sizeof(Linknode));
pNode->data = tData;
return pNode;
}
//销毁结点
void dastory_link(Link **pLink)
{
Linknode *pTmp = (*pLink)->pHead;
if(NULL == pLink || NULL == *pLink)
{
return;
}
while(pTmp != NULL)
{
(*pLink)->pHead = pTmp->pNext;
free(pTmp);
pTmp = (*pLink)->pHead;
}
(*pLink)->count = 0;
}
//初始化
int create_client(struct sockaddr_in my_addr)
{
int sock_fd;
//创建流式套接字
if((sock_fd = socket(AF_INET, SOCK_STREAM,0)) == -1)
{
perror("sock_fd error");
return -1;
}
//等待服务器端连接
if((connect(sock_fd, (struct sockaddr*)&my_addr, sizeof(my_addr))) == -1)
{
perror("connect_fd error");
close(sock_fd);
return -1;
}
return sock_fd;
}
//遍历链表
char *link_find(Link *pLink, int index)
{
Linknode *pTmp = pLink->pHead;
while(pTmp != NULL)
{
if(index == pTmp->data.nume)
{
return pTmp->data.name;
}
pTmp = pTmp->pNext;
}
return DOWNLOAD_FILE_ERROR;
}
//开关
int on_off()
{
char a;
getchar();
a = getchar();
if(a == '\n')
{
return 1;
}
return -1;
}
int main(char argc, char *argv[])
{
int my_port, my_id, sock_fd, connect_fd, ret, bank;
char buf[1024];
struct sockaddr_in my_addr;
memset(&my_addr, 0, sizeof(my_addr));
//开辟链表空间
Link *pLink = creat_link();
//入参检查
//端口检查
if(argc != 3)
{
printf("请输入正确信息\n");
return -1;
}
if(atoi(argv[2]) <= 5000)
{
printf("端空小!\n");
return -1;
}
if(argv[1])
{
my_id = inet_addr(argv[1]);//将字符串转化为整形
}
else
{
my_id = inet_addr("192.168.2.51");//将IP地址改为大端
}
//分配IP与端口号
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(atoi(argv[2]));
my_addr.sin_addr.s_addr = my_id;
//注册账户
if(enroll_user(my_addr) < 0)
{
printf(" \n");
printf(" >>>注册失败\n");
return -1;
}
printf(" \n");
printf(" >>>注册成功<<<\n");
//操作
while(1)
{
putchar(10);
printf(" |--------------------------------|\n");
printf(" | |\n");
printf(" | 【1】刷新页面 【2】进入浏览 |\n");
printf(" | |\n");
printf(" | 【3】我要发布 【4】退出 |\n");
printf(" | |\n");
printf(" | 【5】删除标题 |\n");
printf(" | |\n");
printf(" |--------------------------------|\n");
putchar(10);
printf(" 请选择>>>>>:");
scanf("%d", &bank);
switch(bank)
{
case 1:find_file(my_addr);break;
case 2:
get_file(my_addr, pLink);
look_word(my_addr, pLink);
break;
case 3:put_file(my_addr);break;
case 4:quit_file(my_addr);return 0;
case 5:delete_title(my_addr, pLink);break;
}
}
return 0;
}
进入浏览程序
//进入浏览
int get_file(struct sockaddr_in my_addr, Link *pLink)
{
data_t tData;
char buf[1024] = "L", filename[30];
int sock_fd, index = 0, ret = 0, i = 0;
Linknode *pNode; //创建结点保存文件名和对应下标
//初始化 获得接受套接字
if((sock_fd = create_client(my_addr)) == -1)
{
printf("create_client error\n");
return -1;
}
//发送给服务器 服务器执行look_word函数
send(sock_fd, buf, sizeof(buf), 0);
//接受服务器查询出来的文件名
putchar(10);
while((recv(sock_fd, buf, sizeof(buf), 0)) > 0)
{
if(0 == (strcmp(buf, UPLOAD_FILE_SUCCESS))) //判断服务器是否发送完毕
{
break;
}
if(0 == (strcmp(buf, DOWNLOAD_FILE_ERROR))) //判断服务器是否出错
{
printf("find error\n");
return -1;
}
printf(" |______________________\n");
printf(" | 标题%d:%s\n", i++, buf); //打印文件名 为读者提供方便
//头部插入 每接受到一个文件名都通过链表去保存 文件名与下标
strcpy(tData.name, buf);
//创建新结点去保存
pNode = creat_node(tData);
if(NULL == pNode)
{
return -1;
}
pNode->pNext = pLink->pHead;
pLink->pHead = pNode;
pNode->data.nume = pLink->count;
pLink->count++;
usleep(50);
}
close(sock_fd);
}
文章阅读程序
//浏览阅读
int look_word(struct sockaddr_in my_addr, Link *pLink)
{
int sock_fd, index = 0, size;
char filename[30], buf[8000];
struct stat pock;
//初始化
if((sock_fd = create_client(my_addr)) == -1)
{
printf("create_client error\n");
return -1;
}
//要上传文件的名字
putchar(10);
printf(" 请点击您要进入的标题>>>:");
scanf("%d",&index);
//链表遍历查找
strcpy(filename, link_find(pLink, index));
if(0 == strcmp(filename, DOWNLOAD_FILE_ERROR))
{
printf("没有找到\n");
return -1;
}
sprintf(buf, "G#../file/%s", filename);
stat(filename, &pock);
//发送
send(sock_fd, buf, sizeof(buf), 0);
//接受 判断消息是否为DOWNLOAD_FILE_ERROR 或出错
if((size = recv(sock_fd, buf, sizeof(buf), 0)) < 0)
{
perror("recv error");
return -1;
}
if(0 == strcmp(buf, DOWNLOAD_FILE_ERROR))
{
printf("文件不存在\n");
return -1;
}
//文件存在并且接收到size 接受文件内容 打开帖子
putchar(10);
printf(" >>>该篇文章内容为:<<<\n");
putchar(10);
while((recv(sock_fd, buf, 8000, 0)) > 0)
{
printf("%s",buf);
memset(buf, 0, sizeof(buf));
usleep(2000);
}
if(on_off())
{
close(sock_fd);
//销毁结点
dastory_link(&pLink);
return -1;
}
printf("开关失效\n");
}
查找显示程序
int find_file(struct sockaddr_in my_addr)
{
char buf[1024] = "F";
int sock_fd, ret, i = 0;
Save save;
memset(&save, 0, sizeof(save));
//初始化
if((sock_fd = create_client(my_addr)) == -1)
{
printf("create_client error\n");
return -1;
}
//发送
send(sock_fd, buf, sizeof(buf), 0);
//接受
while((recv(sock_fd, &save, sizeof(save), 0)) > 0)
{
if(0== (strcmp(save.pock, DOWNLOAD_FILE_ERROR)))
{
printf("find error");
return -1;
}
putchar(10);
if(0 == i)
{
printf(" >>>>>>>>文章标题:%s<<<<<<<",save.pock);
}
if(i > 0 && i < 3)
{
printf(" >>>%s ",save.pock);
}
putchar(10);
memset(&save, 0, sizeof(save));
usleep(50);
if(++i >= 3)
{
printf("\n");
i = 0;
}
}
if(on_off())
{
close(sock_fd);
return -1;
}
printf("开关失效\n");
}
发布文章程序
//把../put_file/filename里面保存的文件上传到../file/里面
int put_file(struct sockaddr_in my_addr)
{
char filename[30], pock[128], buf[1024], i;
int sock_fd, fd, size = 0;
//初始化
if((sock_fd = create_client(my_addr)) == -1)
{
printf("create_client error\n");
return -1;
}
//需要发布的帖子
printf("需要发布的帖子:");
scanf("%s", filename);
sprintf(buf, "P#%s",filename);
//动画
printf(" >>>>确定发布: 【y】 【n】\n");
putchar(10);
printf(" 请输入>>>:");
getchar();
i = getchar();
if(i == 'n')
{
putchar(10);
printf(" >>>>已取消<<<<\n");
return -1;
}
//发送拼装好的协议
send(sock_fd, buf, sizeof(buf), 0);
//接受消息并 判断
//成功 UPLOAD_FINE_SUCCESS 失败 DOWNLOAD_FILE_ERROR
if((recv(sock_fd, buf, sizeof(buf), 0)) < 0)//判断是否出错
{
perror("recv error");
return -1;
}
if(0 == strcmp(buf, DOWNLOAD_FILE_ERROR))//判断接受的内容是否为DOWN...
{
printf("名字已经存在请换名 或者 路径中没有该文件 请编译成功\n"); //文件存在对应路径中
return -1;
}
//打开要上传帖子的文件
sprintf(pock, "../put_file/%s", filename);
if((fd = open(pock, O_RDWR, 0666)) == -1)
{
perror("open error");
return -1;
}
//将读到的内容发送到服务器
while((size = read(fd, buf, sizeof(buf))) > 0)
{
send(sock_fd, buf, size, 0);
memset(buf, 0, sizeof(buf));
usleep(50);
}
putchar(10);
printf(" >>>>发布成功<<<<\n");
close(fd);
close(sock_fd);
}
退出程序
//退出
void quit_file(struct sockaddr_in my_addr)
{
char buf[1024] = "Q";
int sock_fd;
//初始化
if((sock_fd = create_client(my_addr)) == -1)
{
printf("create_client error\n");
return;
}
//发送
send(sock_fd, buf, sizeof(buf), 0);
return;
}
注册程序
//注册
int enroll_user(struct sockaddr_in my_addr)
{
char buf[1024];
int sock_fd;
//用户名
printf(" >>>>注册新用户<<<<\n");
printf(" \n");
printf(" 请输入用户名>>>:");
scanf("%s", name);
printf(" \n");
printf(" 请输入密码>>>:");
scanf("%s", key);
//初始化
if((sock_fd = create_client(my_addr)) == -1)
{
printf("create_client error\n");
return -1;
}
//加工
sprintf(buf, "E#%s#%s", name, key);
//发送
send(sock_fd, buf, sizeof(buf), 0);
return 1;
}
删除文章程序
//删除标题
int delete_title(struct sockaddr_in my_addr, Link *pLink)
{
char buf[1024], filename[1024] = {0};
int sock_fd;
//初始化
if((sock_fd = create_client(my_addr)) == -1)
{
printf("create_client error\n");
return -1;
}
printf("想要删除的标题名>>>:");
scanf("%s", filename);
//加工
sprintf(buf, "D#%s", filename);
//发送
send(sock_fd, buf, sizeof(buf), 0);
if((recv(sock_fd, buf, sizeof(buf), 0)) < 0)//判断是否出错
{
perror("recv error");
return -1;
}
if(0 == strcmp(buf, DOWNLOAD_FILE_ERROR))//判断接受的内容是否为DOWN...
{
printf("删除失败\n"); //文件存在对应路径中
return -1;
}
printf("删除成功\n");
close(sock_fd);
}
服务器端
主程序
#include <stdio.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <dirent.h>
#include <sqlite3.h>
#include <time.h>
#define N 1024
//错误标志
#define DOWNLOAD_FILE_ERROR "download_file_error"
//成功标志
#define UPLOAD_FILE_SUCCESS "upload_file_success"
//数据库操作🔓
pthread_mutex_t g_mutex;
//数据库的句柄
sqlite3 *db = NULL;
//注册用户名
char key[30] = {0}, name[128] = {0};
//保存文件名结构体
typedef struct save
{
char pock[128];
}Save;
//创建数据库表
int SQL_create(char *sql)
{
char *errmsg = NULL;
//创建数据库
if((sqlite3_exec(db, sql, NULL, NULL, &errmsg)) != SQLITE_OK)
{
printf("SQL_create error:%s\n", errmsg);
sqlite3_free(errmsg);
return -1;
}
printf("SQL_create success\n");
return 1;
}
//打开数据库 不存在则创建
void SQL_open(const char *SQL_name)
{
printf("%s\n", SQL_name);
if((sqlite3_open(SQL_name, &db)) != SQLITE_OK)
{
printf("sqlite3_open error\n");
return;
}
printf("sqlite3_open success\n");
}
//空格建退出
void quit_file()
{
printf("客户端退出\n");
return;
}
int main(char argc, char *argv[])
{
/*
struct stat pock;
stat(SIZE,&pock);
printf("文件大小:%ld\n",pock.st_size);
*/
int my_port, sock_fd, connect_fd;
struct sockaddr_in my_addr;
memset(&my_addr, 0, sizeof(my_addr));
char buf[1024];
pthread_t tid;
//入参检查
//端口检查
if(argv[1]) //判断端口号
{
my_port = atoi(argv[1]);//将字符串转化为整形
}
else
{
my_port = 5888;
}
//创建流式套接字
if((sock_fd = socket(AF_INET, SOCK_STREAM,0)) == -1)
{
perror("sock_fd error");
return -1;
}
printf("sock_fd success\n");
//优化
int on = 1;
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
//绑定IP 端口号
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(my_port);
printf("my_port:%d\n", my_port);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if((bind(sock_fd, (struct sockaddr*)&my_addr, sizeof(my_addr))) == -1)
{
perror("bind error");
close(sock_fd);
return -1;
}
printf("bind success\n");
//设置监听模式
if((listen(sock_fd, 10)) == -1)
{
perror("listen error");
close(sock_fd);
return -1;
}
printf("Listening......\n");
//打开并创建数据库
SQL_open("campus.db");
//创建数据库表
char sql[] = "create table if not exists campus(file_name text primary key not null, creater text not null, time text);";
SQL_create(sql);
//选择 操作
while(1)
{
//等待客户端的连接
if((connect_fd = accept(sock_fd, NULL, NULL)) == -1)
{
perror("accept error");
close(sock_fd);
continue;
}
printf("创建的连接描述符:%d\n",connect_fd);
//创建线程
pthread_create(&tid, NULL, choose_fun, (void*)&connect_fd);
pthread_detach(tid);
}
close(sock_fd);
return 0;
}
选择程序
void *choose_fun(void *arg)
{
int connect_fd = *(int *)arg, ret;
char buf[1024], key[30], name[128];
printf("接受消息\n");
//接受客户端消息 判断选择那种模式 F查找 G下载 P上传
if((ret = recv(connect_fd, buf, sizeof(buf), 0)) == -1)
{
perror("rece error");
return NULL;
}
//判断对端是否退出
if(0 == ret)
{
printf("客户端退出!\n");
return NULL;
}
printf("接受客户端buf[0]内容: %c\n", buf[0]);
//1.套接字 2.文件名加路径
switch(buf[0])
{
case 'F':
find_file(connect_fd);
break;
case 'P':
printf("%s\n",buf);
put_file(connect_fd, buf+2);
break;
case 'G':
printf("%s\n",buf);
get_file(connect_fd, buf+2);
break;
case 'L':
printf("%s\n",buf);
look_word(connect_fd);
break;
case 'Q':
quit_file();
break;
case 'E':
enroll_file(connect_fd,buf+2);
break;
case 'D':
delete_title(connect_fd, buf+2);
break;
}
}
下载文件程序
//下载
void get_file(int connect_fd, char filename[30])
{
char buf[8000];
int fd, mode = 0;
struct stat pock;
stat(filename, &pock);
printf("文件大小:%ld\n",pock.st_size);
//检查文件是否存在数据库中 不存在就无法下载
//文件路径../file/
if((SQL_file_exist(filename)+8) < 0)//文件不存在 发DOWNLOAD_FILE_ERROR
{
printf("不存在\n");
strcpy(buf, DOWNLOAD_FILE_ERROR);
}
else //文件存在 发文件大小
{
//检查文件是否存在对应路径中的文件夹
if((access(filename, mode)) == -1)
{
printf("文件不在对应的路径中\n");
strcpy(buf, DOWNLOAD_FILE_ERROR);
}
else
{
printf("在数据库中文件存在\n");
sprintf(buf, "%ld", pock.st_size);
}
}
send(connect_fd, buf, sizeof(buf), 0);//将获得的buf内容发给client
if(0 == strcmp(buf, DOWNLOAD_FILE_ERROR))
{
printf("文件%s出错\n",buf);
return;
}
//打开文件
if((fd = open(filename, O_RDWR)) == -1)
{
printf("open error\n");
return;
}
printf("打开文件成功\n");
//读取内容
printf("size文件大小:%ld\n", pock.st_size);
while((read(fd, buf, pock.st_size)) > 0)
{
send(connect_fd, buf, pock.st_size, 0);
memset(buf, 0, sizeof(buf));
usleep(2000);
}
close(fd);
close(connect_fd);
}
上传文件程序
//上传
void put_file(int connect_fd, char filename[30])
{
char buf[1024], sql[128], pock[128];
int fd, mode = 0;
struct stat Size;
//检查文件是否存在数据库中
sprintf(pock, "../put_file/%s", filename);
if((SQL_file_exist(filename)) < 0)//数据库中没有一样的文件名 就通过
{
//检查文件是否存在对应路径中的文件夹
if((access(pock, mode)) == -1) //返回-1表示文件不存在
{
printf("路径中没有该文件 请编译通过\n");
strcpy(buf, DOWNLOAD_FILE_ERROR);
}
else
{
printf("路径中存在 可以上传\n");
strcpy(buf, UPLOAD_FILE_SUCCESS);
}
}
else //文件名存在数据库
{
printf("在数据库中文件存在 请更换文件名\n");
strcpy(buf, DOWNLOAD_FILE_ERROR);
}
send(connect_fd, buf, sizeof(buf), 0);//将获得的buf内容发给client
//再次判断
if(0 == strcmp(buf, DOWNLOAD_FILE_ERROR))
{
printf("文件%s出错\n",buf);
return;
}
stat(pock,&Size);
int i = Size.st_size;
printf("文件大小:%d\n", i);
//文件名保存到数据库
char len[20] = {0};
time_t timep;
time(&timep);
struct tm *p;
p = gmtime(&timep);
snprintf(len, 20, "%d-%d-%d %d:%d:%d", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, 8 + p->tm_hour, p->tm_min, p->tm_sec);
printf("时间%s\n:", len);
sprintf(sql, "insert into campus values('%s', '发布人:%s', '发布时间:%s');", filename, name, len);
if((SQL_create(sql)) == -1)
{
printf("文件上传失败\n");
return;
}
//将文件保存到文件夹中
sprintf(pock, "../file/%s", filename);
if((fd = open(pock, O_CREAT | O_RDWR | O_TRUNC, 0666)) == -1)
{
perror("open error");
return;
}
//把接收到文件的内容写入到打开的路径中
//while((recv(connect_fd, buf, sizeof(buf), 0)) > 0)
if(i >= N)
{
i = N;
}
while((recv(connect_fd, buf, i, 0)) > 0)
{
printf("buf里面的字符个数%ld\n", strlen(buf));
write(fd, buf, strlen(buf));
memset(buf, 0, sizeof(buf));
usleep(50);
}
printf("发布成功\n");
close(fd);
close(connect_fd);
}
注册程序
//注册
int enroll_file(int connect_fd, char buf[1024])
{
char *pock = buf;
int i = 0;
while(1)
{
if('#' != buf[i])
{
name[i] = buf[i];
++pock;
++i;
continue;
}
strcpy(key, ++pock);
break;
}
printf("name=%s\n", name);
printf("key=%s\n", key);
//创建数据库表
char sql[1024] = {0};
sprintf(sql, "create table if not exists %s(user text primary key not null, key text not null);", name);
printf("sql=%s\n", sql);
SQL_create(sql);
printf("创建成功");
}
删除文件程序
//删除标题
int delete_title(int connect_fd, char filename[1024])
{
char sql[128] = {0}, buf[1024] = {0};
printf("name=%s\n", filename);
sprintf(sql, "delete from campus where file_name='%s';", filename);
if(SQL_create(sql)< 0)
{
printf("删除失败\n");
strcpy(buf, DOWNLOAD_FILE_ERROR);
}
else
{
printf("删除成功\n");
strcpy(buf, UPLOAD_FILE_SUCCESS);
}
send(connect_fd, buf, sizeof(buf), 0);//将获得的buf内容发给client
close(connect_fd);
}