传文件通用(结构体)
通过结构体传文件
服务器代码:
#include <stdio.h> #include <pthread.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/ip.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <sys/stat.h> #define N 512 //每次上传一个结构体 typedef struct file { int len_max;//文件最大长度 int len;//本次传输的长度 char buf[N];//传输的内容 }File; //传输显示 void bar(int x,int max) { system("clear"); int i,k; k = x*1.0/max*100; printf("/"); for(i = 0; i < k/5; i++) { printf("#"); } for(i = 0; i < 20-k/5; i++) { printf("*"); } printf("/%d%%\n",k); //延时只是为了显示效果没啥用可以自己调 usleep(50000); } //套接字初始化 //三个参数分别为IP、端口号、允许最大连接 int tcp_server_init(char *ip, int port, int backlog) { //创建套接字文件打通软件和硬件的关节 int skt = socket(AF_INET, SOCK_STREAM, 0); if(-1 == skt) { printf("socker error\n"); return -1; } //将IP和端口号存入结构体 struct sockaddr_in sddr; sddr.sin_family = AF_INET; sddr.sin_port = htons(port); sddr.sin_addr.s_addr = inet_addr(ip); //将套接字和IP、端口号进行绑定 int ret = bind(skt, (struct sockaddr *)&sddr, sizeof(sddr)); if(-1 == ret) { printf("bind error\n"); return -1; } //监听套接字并设置最大链接数量 ret = listen(skt, backlog); if(-1 == ret) { printf("listen error\n"); return -1; } puts("listen...."); return skt; } //连接函数 //参数是打开的套接字文件描述符 int tcp_wait_connect(int skt) { struct sockaddr_in cddr; int len = sizeof(cddr); int nfd = accept(skt, (void *)&cddr, &len); if(-1 == nfd) { perror("accept error\n"); return -1; } return nfd; } int main(int argc, char *argv[]) { char tmp[3] = {'\0'}; int skt = tcp_server_init("0.0.0.0", 6666, 10); int nfd = tcp_wait_connect(skt); File file = {'\0'}; read(nfd, tmp, sizeof(tmp)); int fr = open(argv[1], O_RDONLY); if(-1 == fr) { printf("open error\n"); return -1; } //计算文件大小 struct stat str; stat(argv[1], &str); file.len_max = str.st_size; int count = 0; if(0 == strcmp(tmp,"go")) { while(1) { file.len = read(fr, file.buf, sizeof(file.buf)); count = file.len + count; bar(count, file.len_max); write(nfd, &file, sizeof(file)); if(0 == file.len) { break; } } } printf("上传完成!\n"); close(fr); close(skt); close(nfd); return 0; }
客户端代码:
#include <stdio.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <arpa/inet.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> //一次接收的字节数建议不要超过512且需要与服务器一次上传的字节数一至 #define N 512 //每次接收一个结构体 typedef struct file { int len_max;//文件最大长度 int len;//本次传输的长度 char buf[N];//传输的内容 }File; //传输显示 void bar(int x,int max) { system("clear"); int i,k; k = x*1.0/max*100; printf("/"); for(i = 0; i < k/5; i++) { printf("#"); } for(i = 0; i < 20-k/5; i++) { printf("*"); } printf("/%d%%\n",k); //延时只是为了显示效果没啥用可以自己调 usleep(50000); } int main(int argc, char *argv[]) { //创建套接字 int skt = socket(AF_INET, SOCK_STREAM, 0); if(-1 == skt) { printf("socket error\n"); return -1; } //将IP、端口号存入结构体 struct sockaddr_in sddr; sddr.sin_family = AF_INET; sddr.sin_port = htons(atoi(argv[2])); sddr.sin_addr.s_addr = inet_addr(argv[1]); //绑定 int ret = connect(skt, (struct sockaddr *)&sddr, sizeof(sddr)); if(-1 == ret) { printf("connect error\n"); return -1; } //标识符 char tmp[3] = {'\0'}; File file = {'\0'}; //创建或打开一个文件存放下载的内容 int fr = open(argv[3], O_WRONLY | O_CREAT | O_TRUNC, 0666); if(-1 == fr) { printf("open error\n"); return -1; } printf("要开始吗?"); int count = 0; //输入指定字符开始下载 fgets(tmp,sizeof(tmp),stdin); write(skt, tmp, 2); while(1) { read(skt, &file, sizeof(file)); if(0 == file.len) { break; } count = file.len + count; bar(count, file.len_max); write(fr, file.buf, file.len); } printf("下载完成!\n"); close(skt); close(fr); return 0; }
Makefile
APP: gcc -g server.c -o server gcc -g app.c -o app R1: ./server qy.jpg R2: ./app 192.168.10.159 6666 wf.jpg