使用posix_quic-master传输文件
2019-06-10 09:20
639 查看
首先修改原函数的客户端
#include "quic_socket.h" #include "debug.h" #include <string.h> #include <stdio.h> #include <string> #include <sys/epoll.h> #include <sys/poll.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> using namespace posix_quic; #define CHECK_RES(res, api) \ do {\ if (res < 0) {\ perror(api " error");\ return 1;\ }\ } while (0) bool gIsTestReset = false; bool gIsTestSocketReset = false; bool gIsTestSocketResetWithStream = false; QuicSocket conn = -1; void onStreamClose() { if (gIsTestSocketReset) { QuicCloseSocket(conn); } } int doLoop(QuicEpoller ep) { struct epoll_event evs[1024];// //收集epoll事件中已经发送的事件 int n = QuicEpollWait(ep, evs, sizeof(evs)/sizeof(struct epoll_event), 6000); //检查n的返回值 CHECK_RES(n, "epoll_wait"); int res; for (int i = 0; i < n; i++) { struct epoll_event & ev = evs[i]; int fd = ev.data.fd; EntryCategory category = GetCategory(fd);//判断监听事件种类 UserLog("QuicEpoller trigger: fd = %d, category = %s, events = %s", fd, EntryCategory2Str((int)category), EpollEvent2Str(ev.events)); if (ev.events & EPOLLOUT) { // connected UserLog("Connected.\n"); if (category == EntryCategory::Socket) { QuicStream stream = QuicCreateStream(fd);//创建stream流 assert(stream > 0); struct epoll_event ev; ev.data.fd = stream; ev.events = EPOLLIN; //将stream加入到ep中去 res = QuicEpollCtl(ep, EPOLL_CTL_ADD, stream, &ev); CHECK_RES(res, "epoll_ctl"); //将hello quic这几个字符串写入到sstream流中去 // std::string s = "Hello quic!"; char r_file[]="/home/IPcom/Downloads/posix_quic-master/test/client/test.txt"; FILE *r_ptr=NULL; r_ptr= fopen(r_file,"rb"); if(r_ptr == NULL) { printf("error"); return 0; } char buffer[1024]; int length=0; while(!feof(r_ptr)) { length=fread(buffer,1,1024,r_ptr);//128 } res = QuicWrite(stream, buffer, length, false); CHECK_RES(res, "write"); } } /** if (ev.events & EPOLLIN) {//如果是读事件 UserLog("QuicDebugInfo:\n%s\n", GlobalDebugInfo(src_all).c_str()); if (category == EntryCategory::Socket) {//判断是否client连接 // client needn't accept } else if (category == EntryCategory::Stream) {//判断是否是stream事件 // stream, recv data. char buf[10240]; res = QuicRead(fd, buf, sizeof(buf));//读事件 CHECK_RES(res, "read"); UserLog("recv(len=%d): %.*s\n", res, res, buf); //bool gIsTestSocketResetWithStream = false; //QuicSocket conn = -1; if (gIsTestSocketResetWithStream) QuicCloseSocket(conn); else if (std::string(buf, res) != "Bye") {//如果没有输入bye std::string s = "Bye"; //bool gIsTestReset = false; if (gIsTestReset) { res = QuicWrite(fd, s.c_str(), s.size(), false); CHECK_RES(res, "write"); QuicCloseStream(fd); onStreamClose(); } else { res = QuicWrite(fd, s.c_str(), s.size(), true); CHECK_RES(res, "write"); } } } } */ if (ev.events & EPOLLERR) { if (category == EntryCategory::Socket) { UserLog("Close Socket fd=%d\n", fd); QuicCloseSocket(fd); } else if (category == EntryCategory::Stream) { UserLog("Close Stream fd=%d\n", fd); QuicCloseStream(fd); onStreamClose(); } } } return 0; } int main() { //uint64_t debug_mask = 0; 64位无符号数 //enum posix_quic::eDbgMask::dbg_all = 4294967295L //enum posix_quic::eDbgMask::dbg_timer = 1024L debug_mask = dbg_all & ~dbg_timer; // 真正的epoll fd, 可用poll、epoll监听 // typedef int QuicEpoller; //返回epoll句柄 QuicEpoller ep = QuicCreateEpoll(); //判断表达式是否是真 assert(ep >= 0); //创建一个udp套接字 QuicSocket socket = QuicCreateSocket(); assert(socket > 0); conn = socket; int res; //初始化地址 struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(9700); addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //建立udp连接 res = QuicConnect(socket, (struct sockaddr*)&addr, sizeof(addr)); assert(errno == EINPROGRESS); assert(res == -1); //告诉内核要监听什么事件 struct epoll_event ev; ev.data.fd = socket; ev.events = EPOLLIN | EPOLLOUT;//输入输出事件 //将socket套接字加入到ep res = QuicEpollCtl(ep, EPOLL_CTL_ADD, socket, &ev); //判断res是否大于0 CHECK_RES(res, "epoll_ctl"); for (;;) { res = doLoop(ep); if (res != 0) return res; } }
这里我们使用一些文件操作的函数
char r_file[]="/home/IPcom/Downloads/posix_quic-master/test/client/test.txt"; FILE *r_ptr=NULL; r_ptr= fopen(r_file,"rb"); if(r_ptr == NULL) { printf("error"); return 0; } char buffer[1024]; int length=0; while(!feof(r_ptr)) { length=fread(buffer,1,1024,r_ptr);//128 }
这篇博客介绍了fopen函数 可以参考一下
添加链接描述
fread()函数在这篇博客中得以介绍添加链接描述
下面附上服务器端
#include "quic_socket.h" #include "debug.h" #include <string.h> #include <stdio.h> #include <string> #include <sys/epoll.h> #include <sys/poll.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> #include <fstream> using namespace posix_quic; #define CHECK_RES(res, api) \ do {\ if (res < 0) {\ perror(api " error");\ return 1;\ }\ } while (0) int OnRead(QuicStream fd) { int res; char buf[10240]; for (;;) { res = QuicRead(fd, buf, sizeof(buf)); if (res < 0) { if (errno == EAGAIN) return 0; QuicCloseStream(fd); return 1; } else if (res == 0) { QuicStreamShutdown(fd, SHUT_WR); return 1; } UserLog("recv(len=%d): %.*s\n", res, res, buf); std::ofstream OsWrite("test.txt",std::ofstream::app); OsWrite<<buf; OsWrite<<std::endl; OsWrite.close(); res = QuicWrite(fd, buf, res, false);CHECK_RES(res, "write"); } } int doLoop(QuicEpoller ep, QuicSocket listenSock) { struct epoll_event evs[1024]; int n = QuicEpollWait(ep, evs, sizeof(evs)/sizeof(struct epoll_event), 6000); CHECK_RES(n, "epoll_wait"); int res; for (int i = 0; i < n; i++) { struct epoll_event & ev = evs[i]; int fd = ev.data.fd; EntryCategory category = GetCategory(fd); UserLog("QuicEpoller trigger: fd = %d, category = %s, events = %s", fd, EntryCategory2Str((int)category), EpollEvent2Str(ev.events)); if (ev.events & EPOLLOUT) { // 此次测试中, 协议栈5MB的缓冲区足够使用, 不再创建额外的用户层缓冲区. UserLog("Ignore EPOLLOUT\n"); } if (ev.events & EPOLLIN) { if (category == EntryCategory::Socket) { if (fd == listenSock) { // accept socket // UserLog("QuicDebugInfo:\n%s\n", GlobalDebugInfo(src_all).c_str()); for (;;) { QuicSocket newSocket = QuicSocketAccept(fd); if (newSocket > 0) { struct epoll_event ev; ev.data.fd = newSocket; ev.events = EPOLLIN; res = QuicEpollCtl(ep, EPOLL_CTL_ADD, newSocket, &ev); CHECK_RES(res, "epoll_ctl"); UserLog("Accept Socket fd=%d, newSocket=%d\n", fd, newSocket); } else { UserLog("No Accept Socket. fd=%d\n", fd); break; } } } else { // accept stream for (;;) { QuicStream newStream = QuicStreamAccept(fd); if (newStream > 0) { struct epoll_event ev; ev.data.fd = newStream; ev.events = EPOLLIN; res = QuicEpollCtl(ep, EPOLL_CTL_ADD, newStream, &ev); CHECK_RES(res, "epoll_ctl"); UserLog("Accept Stream fd=%d, newSocket=%d\n", fd, newStream); OnRead(newStream); } else { UserLog("No Accept Stream. fd=%d\n", fd); break; } } } } else if (category == EntryCategory::Stream) { // stream, recv data. OnRead(fd); } } if (ev.events & EPOLLERR) { if (category == EntryCategory::Socket) { UserLog("Close Socket fd=%d\n", fd); QuicCloseSocket(fd); } else if (category == EntryCategory::Stream) { UserLog("Close Stream fd=%d\n", fd); QuicCloseStream(fd); } } } return 0; } int main() { debug_mask = dbg_all & ~dbg_timer; Q在这里插入片uicEpoller ep = QuicCreateEpoll(); assert(ep >= 0); QuicSocket socket = QuicCreateSocket(); assert(socket > 0); int res; struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(9700); addr.sin_addr.s_addr = inet_addr("127.0.0.1"); res = QuicBind(socket, (struct sockaddr*)&addr, sizeof(addr)); CHECK_RES(res, "bind"); struct epoll_event ev; ev.data.fd = socket; ev.events = EPOLLIN | EPOLLOUT; res = QuicEpollCtl(ep, EPOLL_CTL_ADD, socket, &ev); CHECK_RES(res, "epoll_ctl"); for (;;) { res = doLoop(ep, socket); if (res != 0) return res; } }
读取并存放文件使用的是这一步骤
std::ofstream OsWrite("test.txt",std::ofstream::app); OsWrite<<buf; OsWrite<<std::endl; OsWrite.close(); res = QuicWrite(fd, buf, res, false);
相关文章推荐
- 使用PSCP传输文件方法
- PuTTY 提供的文件传输工具PSCP (PuTTY Secure Copy client) 基本使用说明
- asp.net文件上传用到html的file控件,在使用母版页Master,更改form的Enctype=multipart/form-data的方法
- 抛弃WinSCP&nbsp;教你使用CuteFTP传输文件
- 使用3CDaemon 进行ftp 传输文件 (linux->开发板) 的方法
- Java使用Socket进行字符串和图片文件同时传输
- Linux网络编程之使用TCP传输文件
- VC中使用Socket网络文件传输结构
- 使用GridFTP传输文件的简单JAVA代码
- Java Socket实战之七 使用Socket通信传输文件
- Apache CXF实战之七 使用Web Service传输文件
- 发现使用wcf传输的文件有20K的丢失
- 使用SecureCRT在Linux与Windows之间传输文件
- Apache CXF实战之七 使用Web Service传输文件
- win7系统使用多线程加快文件复制与传输
- 使用SerialPort传输图片文件的实验
- 使用ObjectOutputStream或ObjectInputStream传输文件
- 想编一个局域网内的P2P文件传输软件,C++的,基于TCP协议,使用MFC需要建哪些类?
- 如何使用ssh(scp, winscp)在N950/N9(MeeGo)与电脑之间传输文件
- Java Socket实战之七 使用Socket通信传输文件