tcp服务器和客户端实现文件上传和下载
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <arpa/inet.h>
#define N 256
/* 下载文件 */
int do_get(int sockfd, char *buf)
{
int ret;
int fd;
int count;
int filelen;
char * filebuf;
/* 创建文件 */
fd = open(buf+4, O_CREAT | O_RDWR | O_TRUNC, 0777);
if (fd == -1) {
perror("client->open");
return -1;
}
/* 将请求信息写入到套接字文件描述符当中 */
ret = write(sockfd, buf, N);
if (ret == -1) {
perror("client->do_get->write");
return -1;
}
/* 读取文件的大小 */
ret = read(sockfd, &filelen, 4);
if (ret == -1) {
perror("read");
return -1;
}
/* 开辟空间存储从服务器读取的文件内容 */
filebuf = malloc(filelen);
if (NULL == filebuf)
{
printf("malloc fail\n");
return -1;
}
/* 读取服务器发送的文件数据 */
count = 0;
while(count < filelen) {
ret = read(sockfd, filebuf+count, filelen-count);
if (ret == -1) {
perror("read");
return -1;
} else
count += ret;
}
/* 将读取的文件数据写入的文件当中 */
count = 0;
while(count < filelen) {
ret = write(fd, filebuf+count, filelen-count);
if (ret == -1) {
perror("read");
return -1;
} else
count += ret;
}
free(filebuf);
filebuf = NULL;
close(fd);
return 0;
}
/* 将客户端的文件上传到服务器上 */
int do_put(int sockfd, char *buf)
{
int fd;
int filelen;
int ret;
int count;
char *path = buf + 4;
char *filebuf;
struct stat stat_buf;
/* 发送请求 */
#if 1
ret = write(sockfd, buf, N);
if (0 > ret)
{
perror("write");
exit(-1);
}
#endif
/* 打开文件 */
fd = open(path, O_RDONLY);
if (-1 == fd)
{
perror("client->open");
exit (-1);
}
/* 获取文件大小 */
if (-1 == (stat(path, &stat_buf)))
{
perror("stat");
exit(-1);
}
filelen = stat_buf.st_size;
printf("%d\n",filelen);
/* 发送文件长度 */
ret = write(sockfd, &filelen, 4);
if (-1 == ret)
{
perror("write");
exit(-1);
}
/* 开辟空间 */
filebuf = malloc(filelen);
if (NULL == filebuf)
{
printf("malloc fail\n");
return -1;
}
/* 读取文件的内容 */
count = 0;
while(count < filelen)
{
ret = read(fd, filebuf + count, filelen - count);
if (0 > ret)
{
perror("read");
exit(-1);
}
/* else if (0 == ret)
{
printf("read file end\n");
break;
}*/
count += ret;
}
/* 将文件大小发送到套接字文件描述符当中 */
ret = write(sockfd, &filelen, 4);
if (-1 == ret)
{
perror("client->write");
exit(-1);
}
/* 将文件的内容写入到套接字当中 */
count = 0;
while (count < filelen)
{
ret = write(sockfd, filebuf + count, filelen - count);
if (0 > ret)
{
perror("write");
exit(-1);
}
count += ret;
}
/* 释放空间 */
free(filebuf);
filebuf = NULL;
return 0;
}
int do_list(int sockfd, char *buf)
{
int ret;
/* 发送数据请求 */
ret = write(sockfd, buf, N);
if (ret == -1) {
perror("write");
return -1;
}
ret = read(sockfd, buf, N);
if (ret == -1) {
perror("read");
return -1;
}
printf("%s\n", buf);
return 0;
}
int main()
{
int ret;
int sockfd;
char buf[N];
struct sockaddr_in srvaddr;
/* 1. 创建客户端(创建一socket套接字);socket */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
perror("client->socket");
return -1;
}
printf("create sockfd = %d success !!\n", sockfd);
/* 2. 向服务器请求连接,并且建立连接; connect */
memset(&srvaddr, 0, sizeof(struct sockaddr));
srvaddr.sin_family = AF_INET;
srvaddr.sin_port = htons(9998);
srvaddr.sin_addr.s_addr = inet_addr("192.168.2.10");
ret = connect(sockfd, (const struct sockaddr *)&srvaddr, sizeof(struct sockaddr));
if(ret == -1) {
perror("client->connect");
return -1;
}
printf("connect success !!!\n");
while(1) {
/* 5. 读写数据: read/write */
memset(buf, 0, N);
printf("input : ");
fgets(buf, sizeof(buf), stdin); //get 1.c
char *p = strstr(buf, "\n");
*p = '\0';
if (strstr(buf, "get")) {
do_get(sockfd, buf);
} else if (strstr(buf, "put")) {
do_put(sockfd, buf);
} else if (strstr(buf, "list")) {
do_list(sockfd, buf);
}
}
/* 6. 关闭 close; */
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#define N 256
int server_init(char *ip, char *port)
{
int ret;
int listenfd;
struct sockaddr_in srvaddr;
/* 1. 创建服务器(创建一个socket套接字);socket */
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if (listenfd == -1) {
perror("server->socket");
return -1;
}
printf("create listenfd = %d success !!\n", listenfd);
int opt = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
/* 2. 设置服务器的IP地址和端口号(将socket和服务器的IP地址和端口号进行绑定);bind */
memset(&srvaddr, 0, sizeof(struct sockaddr));
srvaddr.sin_family = AF_INET;
srvaddr.sin_port = htons(atoi(port));
srvaddr.sin_addr.s_addr = inet_addr(ip);
ret = bind(listenfd, (const struct sockaddr *)&srvaddr, sizeof(struct sockaddr));
if(ret == -1) {
perror("server->bind");
return -1;
}
printf("bind success !!!\n");
/* 3. 启动监听(启动服务器); listen */
ret = listen(listenfd, 10);
if (ret == -1) {
perror("server->listen");
return -1;
}
printf("listen success !!\n");
return listenfd;
}
int server_wait_connect(int listenfd, struct sockaddr *addr, socklen_t *addrlen)
{
int connfd;
/* 4. 等待客户端的连接请求,如果没有连接请求则等待,如果有连接请求,则建立连接; accept */
connfd = accept(listenfd, addr, addrlen);
if (connfd == -1) {
perror("server->accept");
return -1;
}
printf("connect connfd = %d success \n", connfd);
return connfd;
}
/* 从服务器上的文件下载到客户端 */
int do_get(int connfd, char *buf)
{
int ret;
int fd;
int filelen;
int count;
char *path = buf+4;
char *filebuf;
struct stat stat_buf;
/* 打开文件 */
fd = open(path, O_RDONLY);
if (fd == -1) {
perror("server->open");
return -1;
}
/* 获取文件的大小 */
ret = stat(path, &stat_buf);
if (ret == -1) {
perror("stat");
return -1;
}
filelen = stat_buf.st_size;
printf("%d\n",filelen);
/* 发送文件的大小 */
ret = write(connfd, &filelen, 4);
if (ret == -1) {
perror("server->write");
return -1;
}
/* 开辟空间,用来存储文件数据 */
filebuf = malloc(filelen);
if (filebuf == NULL) {
return -1;
}
/* 读取文件内容 */
count = 0;
while(count < filelen) {
ret = read(fd, filebuf+count, filelen-count);
if (ret == -1) {
perror("read");
return -1;
} else
count += ret;
}
/* 将文件的数据写入到套接字文件描述符当中 */
count = 0;
while(count < filelen) {
ret = write(connfd, filebuf+count, filelen-count);
if (ret == -1) {
perror("write");
return -1;
} else
count += ret;
}
/* 释放空间 */
free(filebuf);
filebuf = NULL;
return 0;
}
/* 将客户端的文件上传到服务器上 */
int do_put(int connfd, char *buf)
{
printf("put\n");
int ret;
int fd;
int count;
int filelen;
char *filebuf;
#if 0
ret = read(connfd, buf, N);
if (-1 == ret)
{
perror("read");
exit(-1);
}
#endif
/* 打开文件 */
fd = open(buf+4, O_RDWR | O_CREAT | O_TRUNC, 0666);
if (0 > fd)
{
perror("server->open");
exit(-1);
}
/* 从套接字文件描述符当中读取文件的大小 */
ret = read(connfd, &filelen, 4);
if (0 > ret)
{
perror("server->process->read");
exit(-1);
}
printf("%d\n",filelen);
/* 开辟空间 */
filebuf = malloc(filelen);
if (NULL == filebuf)
{
printf("malloc fail\n");
return -1;
}
/* 从套接字文件描述符当中读取文件的内容 */
count = 0;
while (count < filelen)
{
ret = read(connfd, filebuf + count, filelen - count);
if (0 > ret)
{
perror("read");
exit(-1);
}
/* else if (0 == ret)
{
printf("read file end\n");
break;
}*/
count += ret;
//printf("read = %d\n",count);
}
/* 将读取的内容写入到文件当中 */
count = 0;
while (count < filelen)
{
ret = write(fd, filebuf + count, filelen - count);
if (0 > ret)
{
perror("write");
exit(-1);
}
count += ret;
//printf("write = %d\n",count);
}
/* 释放空间 */
free(filebuf);
filebuf = NULL;
close(fd);
return 0;
}
int do_list(int connfd, char *buf)
{
int ret;
DIR *dir;
struct dirent *drt;
dir = opendir(".");
if (dir == NULL) {
perror("opendir");
return -1;
}
memset(buf, 0, N);
while(NULL != (drt = readdir(dir))) {
if (drt->d_name[0] == '.')
continue;
strcat(buf, drt->d_name);
strcat(buf, "\t");
}
ret = write(connfd, buf, N);
if (ret == -1) {
perror("write");
return -1;
}
}
int client_process(int connfd)
{
int ret;
char buf[N];
while(1) {
/* 5. 读写数据: read/write; */
memset(buf, 0, sizeof(buf));
ret = read(connfd, buf, sizeof(buf));
//fgets(buf, sizeof(buf),stdin);
//char *p = strstr(buf,"\n");
//*p = '\0';
if (ret == -1)
{
perror("server->read");
return -1;
}
if (strstr(buf, "get"))
{
do_get(connfd, buf);
}
else if (strstr(buf, "put"))
{
do_put(connfd, buf);
}
else if (strstr(buf, "list"))
{
do_list(connfd, buf);
}
}
return 0;
}
int main()
{
int ret;
int listenfd;
int connfd;
char buf[256];
struct sockaddr_in cltaddr;
socklen_t addrlen;
listenfd = server_init("192.168.2.10", "9998");
if (listenfd == -1)
exit(EXIT_FAILURE);
//server_wait_connect(listenfd);
while(1) {
addrlen = sizeof(socklen_t);
memset(&cltaddr, 0, sizeof(struct sockaddr_in));
connfd = server_wait_connect(listenfd, (struct sockaddr *)&cltaddr, &addrlen);
if (connfd == -1)
exit(EXIT_FAILURE);
client_process(connfd);
close(connfd);
}
/* 6. 关闭 close; */
close(listenfd);
return 0;
}
本程序还存在一定的debug