实现代码github仓库地址:戳这里(https://github.com/chensguo8099/network_programming/tree/master/Serv_sendfiles_to_Client)
课程要求:
相关函数:
(一)C/S即客户端(client)与服务器(server),简单文件传输系统的实现运用了网络编程中socket套接字等相关知识,客户端与服务器建立连接用到了许多网络编程相关API函数:
client:connect
server:bind listen accept
参考相关内容:戳这里(http://blog.sina.com.cn/s/blog_12c2b05e90102x6rl.html)
(二)在客户端与服务器建立连接之后我们再使用文件相关知识对服务器端文件内容读出发送至TCP缓冲区,之后再由TCP缓冲区发送至客户端本地空文件中,即实现了服务器与客户端的文件传输功能。其中发送至TCP缓冲区和从TCP缓冲区取数据的过程用到了send,recv函数。
#include < sys/types.h>
#include < sys/socket.h>
ssize_t send(int sockfd, const void*buf, size_t len, int flags);
int sockfd:即accept函数返回的文件描述符
const void* buf:为要发送的缓冲区地址
size_t len:即为发送数据的大小
int flags:一般填0即可
#include < sys/types.h>
#include < sys/socket.h>
ssize_t recv(int sockfd, void* buf,size_t len, int flags);
int sockfd:即套接字文件描述符
void* buf:为要发送的缓冲区地址
size_t len:即为发送数据的大小
int flags:一般填0即可
(三)实现该任务还用到了对文件的读写操作,我们应当将文件数据在服务器端读取出来并发送,然后在客户端创建一个空文件,再将客户端接收到的数据读入到该空文件中,用到了read和write函数。
#include < unistd.h >
ssize_t read(int fd, void* buf, size_tcount);
int fd:当打开一个文件时open函数所返回的文件描述符
void* buf:即为从文件读数据至缓冲区
size_t count:即为读取数据的大小
#include < unistd.h>
ssize_t write(int fd, const void* buf,size_t count);
int fd:当打开一个文件时open函数所返回的文件描述符
void* buf:即为把缓冲区数据写至文件
size_t count:即为读取数据的大小
遇到的问题:
- 开始错误理解为服务器端向客户端发送文件名,之后客户端响应到该文件名并且将该文件发送至服务器端。其中客户端响应服务器发来的文件名时用了strcmp字符串比较函数来确认服务器所发送的文件名在客户端是否存在。
- 理解正确后,在实现数据的发送接收时,起初用到的是c++中的流式输入输出文件(c语言的文件掌握不熟练),但在实现mp3数据传输时未能达到预期效果,然后学习了open,read,write这样的函数,并且去运用,完成了数据流的读出和写入。
代码展示:
1.头文件:
unp.h (head file)
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#ifndef __unp_h
#define __unp_h #include < sys/stat.h> #include < fcntl.h> #include < sys/types.h> #include < sys/socket.h> #include < netinet/in.h> #include < arpa/inet.h> #include < stdio.h> #include < string.h> #include < stdlib.h> #include < sys/un.h> #include < unistd.h > //c++ headfile #include <iostream > #include < fstream> #include < iomanip> #include < cstdio> using namespace std; #ifndef HAVE_BZERO #define bzero(ptr, n) memset(ptr, 0, n) #endif //bzero #define MAXLINE 4096 #define LISTENLINE 1024 #define SA struct sockaddr #endif |
2.服务器(server)
c++ code (server)
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
#include "unp.h" int main(int argc, char **argv) { int sockfd; char sendname[256] = "0"; char recvline[MAXLINE + 1] = "0"; struct sockaddr_in servaddr; sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //AF_INET is IPv4 //int sockfd = socket(AF_INET, SOCK_STREAM, 0); if(sockfd < 0) { printf(">>create socket error < 0"); exit(1); } bzero(&servaddr, sizeof(servaddr)); //memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(9500); if(bind(sockfd, (SA *)&servaddr, sizeof(servaddr)) < 0) { printf(">>bind error\n"); exit(1); }//bind socket if(listen(sockfd, LISTENLINE) < 0) { printf(">>listen error\n"); exit(1); }//listen socket int connfd = accept(sockfd, (SA *)NULL, NULL); if(connfd < 0) { printf(">>accept error\n"); exit(1); }//accept message //------------------send mp3 name---------------------- read(STDIN_FILENO, sendname, sizeof(sendname)); send(connfd, sendname, sizeof(sendname), 0); //----------------------------------------------------- int fd = open("music.mp3", 'r'); char buffer[2048]; while(1) { if(read(fd, buffer, sizeof(buffer) - 1)) { send(connfd, buffer, sizeof(buffer) - 1, 0); } else break; } close(fd); exit(0); } |
3.客户端(client)
c++ code (client)
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
#include "unp.h" int main(int argc, char **argv) { int sockfd; char recvname[256] = "\0"; struct sockaddr_in servaddr; if(argc != 3) { printf(">>please input IP and PORT\n"); exit(1); } //create socket sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(sockfd < 0) { printf(">>create socket error\n"); exit(1); } //init servaddr bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(9500); int connfd = connect(sockfd, (SA *)&servaddr, sizeof(servaddr)); if(connfd < 0) { printf(">>connect error\n"); exit(1); } //-------------------recv mp3 name-------------------- recv(sockfd, recvname, sizeof(recvname), 0); printf(">>mp3 name is : %s\n", recvname); //---------------------------------------------------- char buffer[2048]; int fd = open("NEWmusic.mp3", O_RDWR | O_CREAT); while(recv(sockfd, buffer, sizeof(buffer) - 1, 0) > 0) { write(fd, buffer, sizeof(buffer)); } close(fd); exit(0); } |
运行截图:
1.启动服务器:
总结:
本次设计使我了解socket套接字间通信的过程,并熟悉了文件数据的读出和写入。