tcp服务器客户端文件上传和t下载

6 篇文章 0 订阅
6 篇文章 0 订阅

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

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值