2013-03-28 2 views
3

나는 여기 (나의 첫 번째 질문)와 newbe 조금 새로운데, 나는 프로그래밍 수업을 해 본 적이 없다 ... 혼란스러운 코드에 대해 유감스럽게 생각한다.소켓을 통한 파일 전송이 너무 느리다

소켓을 통해 (클라이언트) 및 수신 (서버) 파일을 작성한이 프로그램은 클라이언트가 루프 당 1024 바이트의 파일을 읽고 송신하여 서버가 파일을 수신하여 파일에 기록합니다. 그것은 잘 작동하지만 문제는 매우 느립니다. 내 컴퓨터에서 내 컴퓨터로 다른 컴퓨터로 파일을 보내는 데 시간이 많이 걸리지 만 예상보다 많은 시간이 걸립니다. 예를 들어 스카 이프를 통해 전송하는 경우 훨씬 빠릅니다. 어떤 단서? (아래 코드는 제가 사용하고있는 코드입니다).

서버 :

// servrecvfile.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 
#undef UNICODE 

#define WIN32_LEAN_AND_MEAN 

#include <windows.h> 
#include <winsock2.h> 
#include <ws2tcpip.h> 
#include <stdlib.h> 
#include <stdio.h> 

// Need to link with Ws2_32.lib 
#pragma comment (lib, "Ws2_32.lib") 
// #pragma comment (lib, "Mswsock.lib") 

#define DEFAULT_BUFLEN 65536 
#define DEFAULT_PORT "8883" 

typedef struct thread_args{ 
    SOCKET ClientSocket; 
    int index; 
} *MYDATA, PM; 

MYDATA pDataArray[100]; 
DWORD WINAPI abc(void*); 

int p=0; 

int abz(){ 
    return p; 
} 

void broadcast(MYDATA *fp, char *b, int index){ 
    for(int i=0; i<=abz(); i++){ 
     if(index != i) 
      send(fp[i]->ClientSocket, b, (int)strlen(b), 0); 
    } 
} 

DWORD WINAPI abc(void* pVoid) 
{ 
    struct thread_args *fp; 
    fp = (struct thread_args *) pVoid; 
    long iResult; 
    int filesize; 
    unsigned char recvbuf[ DEFAULT_BUFLEN]; 
    memset(recvbuf, 0, sizeof(recvbuf)); 
    recv(fp->ClientSocket, (char*)recvbuf, DEFAULT_BUFLEN, 0); 
    FILE *abc = fopen(strtok ((char*)recvbuf,":"), "wb"); 
    filesize = atoi(strtok (NULL,":")); 
    memset(recvbuf, 0, sizeof(recvbuf)); 
    int perc=0; 
    int perc2=0; 
    int counter=0; 
    char a = '%'; 
     do { 
      iResult = recv(fp->ClientSocket, (char*)recvbuf, DEFAULT_BUFLEN, 0); 
      if (iResult > 0) { 
       counter += fwrite (recvbuf , sizeof(char) , iResult , abc); 
       memset(recvbuf, 0, sizeof(recvbuf)); 
       perc2 = ((counter*1.000)/filesize*1.000)*100; 
       if(perc2 != perc){ 
        printf("%d%c\n", perc2, a); 
        perc = perc2; 
       } 
      } 
      else if (iResult == 0) 
       printf("Connection closing...\n"); 
      else { 
       printf("recv failed with error: %d\n", WSAGetLastError()); 
       closesocket(fp->ClientSocket); 
       fclose(abc); 
       WSACleanup(); 
       ExitThread(1); 
      } 
     } while (iResult > 0); 


     fclose(abc); 
     ExitThread(-1); 
} 

int __cdecl main(void) 
{ 
    WSADATA wsaData; 
    int iResult; 

    SOCKET ListenSocket = INVALID_SOCKET; 
    SOCKET ClientSocket = INVALID_SOCKET; 

    struct addrinfo *result = NULL; 
    struct addrinfo hints; 

    int iSendResult; 
    char recvbuf[DEFAULT_BUFLEN]; 
    int recvbuflen = DEFAULT_BUFLEN; 


    // Initialize Winsock 
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData); 
    if (iResult != 0) { 
     printf("WSAStartup failed with error: %d\n", iResult); 
     return 1; 
    } 

    ZeroMemory(&hints, sizeof(hints)); 
    hints.ai_family = AF_INET; 
    hints.ai_socktype = SOCK_STREAM; 
    hints.ai_protocol = IPPROTO_TCP; 
    hints.ai_flags = AI_PASSIVE; 

    // Resolve the server address and port 
    iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result); 
    if (iResult != 0) { 
     printf("getaddrinfo failed with error: %d\n", iResult); 
     WSACleanup(); 
     return 1; 
    } 

    // Create a SOCKET for connecting to server 
    ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); 
    if (ListenSocket == INVALID_SOCKET) { 
     printf("socket failed with error: %ld\n", WSAGetLastError()); 
     freeaddrinfo(result); 
     WSACleanup(); 
     return 1; 
    } 

    // Setup the TCP listening socket 
    iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen); 
    if (iResult == SOCKET_ERROR) { 
     printf("bind failed with error: %d\n", WSAGetLastError()); 
     freeaddrinfo(result); 
     closesocket(ListenSocket); 
     WSACleanup(); 
     return 1; 
    } 

    freeaddrinfo(result); 

    iResult = listen(ListenSocket, SOMAXCONN); 
    if (iResult == SOCKET_ERROR) { 
     printf("listen failed with error: %d\n", WSAGetLastError()); 
     closesocket(ListenSocket); 
     WSACleanup(); 
     return 1; 
    } 

    int i=0; 
    while(1){ 

    // Accept a client socket 
    ClientSocket = accept(ListenSocket, NULL, NULL); 
    if (ClientSocket == INVALID_SOCKET) { 
     printf("accept failed with error: %d\n", WSAGetLastError()); 
     closesocket(ListenSocket); 
     WSACleanup(); 
     return 1; 
    } 
    pDataArray[i] = (MYDATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
       sizeof(PM)); 
    pDataArray[i]->ClientSocket = ClientSocket; 
    pDataArray[i]->index = i; 

     CreateThread( 
      NULL,     // default security attributes 
      0,      // use default stack size 
      abc,  // thread function name 
      pDataArray[i],   // argument to thread function 
      0,      // use default creation flags 
      NULL); // returns the thread identifier 
     p = i; 
     i++; 
    } 

    // No longer need server socket 
    closesocket(ListenSocket); 

    // Receive until the peer shuts down the connection 
    //char a[DEFAULT_BUFLEN]; 





    // shutdown the connection since we're done 
    iResult = shutdown(ClientSocket, SD_SEND); 
    if (iResult == SOCKET_ERROR) { 
     printf("shutdown failed with error: %d\n", WSAGetLastError()); 
     closesocket(ClientSocket); 
     WSACleanup(); 
     return 1; 
    } 

    // cleanup 
    closesocket(ClientSocket); 
    WSACleanup(); 

    return 0; 
} 

클라이언트 : 아무 잘못이있는 경우 7

어떤 도움을 주셔서 감사도 알려

// sendfile.cpp : Defines the entry point for the console application. 
// 
#include "StdAfx.h" 

#define WIN32_LEAN_AND_MEAN 

#include <windows.h> 
#include <winsock2.h> 
#include <ws2tcpip.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 


// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib 
#pragma comment (lib, "Ws2_32.lib") 
#pragma comment (lib, "Mswsock.lib") 
#pragma comment (lib, "AdvApi32.lib") 


#define DEFAULT_BUFLEN 65536 
#define DEFAULT_PORT "8882" 


int __cdecl main(int argc, char **argv) 
{ 
    WSADATA wsaData; 
    SOCKET ConnectSocket = INVALID_SOCKET; 
    struct addrinfo *result = NULL, 
        *ptr = NULL, 
        hints; 
    char *sendbuf = "this is a test"; 
    char recvbuf[DEFAULT_BUFLEN]; 
    int iResult; 
    int recvbuflen = DEFAULT_BUFLEN; 

    char linha[DEFAULT_BUFLEN]; 
    char IP[20], porta[10]; 

    FILE *fp1; 
    fp1 = fopen("config.txt", "r"); 
    if(fp1 == NULL) 
    { 
     printf("Unable to find config.txt.\n"); 
     exit(-1); 
    } 
    while(fgets(linha,DEFAULT_BUFLEN, fp1) !=NULL){ 
     if(strstr(linha, "port=")) 
      sscanf(linha, "port=%s", porta); 
     if(strstr(linha, "ip=")) 
      sscanf(linha, "ip=%s", IP); 
    } 

    fclose(fp1); 


    char filenam[DEFAULT_BUFLEN]; 
    printf("Insert file name: "); 
    scanf ("%s", filenam); 
    FILE *trans = fopen(filenam, "rb"); 

    if(trans == NULL) 
    { 
     printf("File not found\n"); 
     exit(-1); 
    } 


    // Initialize Winsock 
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData); 
    if (iResult != 0) { 
     printf("WSAStartup failed with error: %d\n", iResult); 
     return 1; 
    } 

    ZeroMemory(&hints, sizeof(hints)); 
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_STREAM; 
    hints.ai_protocol = IPPROTO_TCP; 

    // Resolve the server address and port 
    iResult = getaddrinfo(IP, porta, &hints, &result); 
    if (iResult != 0) { 
     printf("getaddrinfo failed with error: %d\n", iResult); 
     WSACleanup(); 
     return 1; 
    } 

    // Attempt to connect to an address until one succeeds 
    for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) { 

     // Create a SOCKET for connecting to server 
     ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, 
      ptr->ai_protocol); 
     if (ConnectSocket == INVALID_SOCKET) { 
      printf("socket failed with error: %ld\n", WSAGetLastError()); 
      WSACleanup(); 
      return 1; 
     } 

     // Connect to server. 
     iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen); 
     if (iResult == SOCKET_ERROR) { 
      closesocket(ConnectSocket); 
      ConnectSocket = INVALID_SOCKET; 
      continue; 
     } 
     break; 
    } 

    freeaddrinfo(result); 

    if (ConnectSocket == INVALID_SOCKET) { 
     printf("Unable to connect to server!\n"); 
     WSACleanup(); 
     return 1; 
    } 



    long lSize; 

     // obtain file size: 
    fseek (trans , 0 , SEEK_END); 
    lSize = ftell (trans); 
    rewind (trans); 
    char a = '%'; 
    // allocate memory to contain the whole file: 
    memset(recvbuf, 0, sizeof(recvbuf)); 
    unsigned char *linha2 = (unsigned char*) malloc (sizeof(unsigned char)* DEFAULT_BUFLEN); 
    //send(ConnectSocket, filenam, (int)strlen(filenam), 0); 
    sprintf(filenam, "%s:%d", filenam, lSize); 
    printf("%d %d\n", send(ConnectSocket, filenam, (int)strlen(filenam), 0), lSize); 
    long counter=0; 
    long read; 
    int perc=0; 
    int perc2=0; 
    while(counter < lSize){ 
     read = fread_s(linha2, DEFAULT_BUFLEN, sizeof(char), DEFAULT_BUFLEN, trans); 
     counter += send(ConnectSocket, (char*)linha2, read, 0); 
     perc2 = ((counter*1.000)/lSize*1.000)*100; 
     if(perc2 != perc){ 

      printf("%d%c\n", perc2, a); 
      perc = perc2; 
     } 

    } 






    fclose(trans); 
    /* 
    do { 
     //memset(a, 0, sizeof(a)); 
     iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0); 
     if (iResult > 0) 
     { 
      printf("%s", recvbuf); 
      memset(recvbuf, 0, sizeof(recvbuf)); 
     } 
     else if (iResult == 0) 
      printf("Connection closed\n"); 
     else 
      printf("recv failed with error: %d\n", WSAGetLastError()); 


    } while(iResult > 0); */ 

    // cleanup 
    closesocket(ConnectSocket); 
    WSACleanup(); 

    return 0; 
} 

내가 창에서 Visual Studio 2010을 사용하고 있습니다 이 질문의 구조.

+2

우선 - 당신의 버퍼 크기는 512 바이트입니다있는 매우 작습니다. 65536으로 변경하고 어떤 효과가 있는지보십시오. 도움이된다면 가장 적합한 물리적 크기가 있습니다 ... –

+0

그냥 시도했지만 효과가 없습니다. – user2220419

+0

한 번에 1024 바이트 이상을 읽고 보내도록'send'를 변경 했습니까? –

답변

1

Windows는 소켓을 통해 파일 데이터를 효율적으로 전송하기 위해 TransmitFile 기능을 제공합니다.

+0

나는 이것을 클라이언트 측에서 시도했다 (서버 측은 동일하게 유지됨). \t 핸들 hFile = CreateFile (argv [1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); \t // WaitForSingleObject (hFile, INFINITE); \t 경우 (HFILE == INVALID_HANDLE_VALUE) \t \t \t \t { \t DisplayError (TEXT ("를 CreateFile")); \t \t \t _tprintf (TEXT ("터미널 오류 : 읽으려면 \"% s \ "파일을 열 수 없습니다. \ n"), argv [1]); \t \t \t return; \t \t \t} 전송 작업 (ConnectSocket, \t HFILE, \t 0 \t 0 \t NULL, \t NULL, TF_DISCONNECT \t); \t CloseHandle (hFile); 그것은 거의 같은 속도입니다. – user2220419

+0

@ user2220419 : 디스크에 제한이 있습니까? 이 컴퓨터에서이 컴퓨터로 보낼 때 디스크를 회전 시키면 한 번에 두 개의 파일에 액세스해야합니다 (읽히는 파일과 쓰여지는 파일). 즉 디스크가 대부분의 시간을이 둘 사이에서 앞뒤로 움직이는 데 소비합니다. 나는 이것이 당신의 문제라고 생각하지 않지만, 램 디스크를 설정하고 그것을 다시 사용하여 테스트 할 수 있다면, 그것은 분명히 우리에게 말할 것입니다. –

+0

나는 TransmiteFile을 시험해 보았고 같은 속도로 갔다. 빨리 갈 수 있다고 생각한다. 도와 주셔서 감사합니다. – user2220419

1

Skype가 파일을 압축하여 네트워크 전송 속도를 크게 높일 수 있습니다. zlib을 사용하여 인라인으로 압축하거나 공개적으로 사용 가능한 많은 것들 (허프만 인코딩 등)에서 직접 구현할 수 있습니다.

현재, 버퍼 크기를 변경해도 성능이 많이 변경되지는 않습니다. 기본 API (file, socket)는 사용자가 읽거나 쓰는 방법에 관계없이 자동으로 버퍼링을 처리하도록 최적화되어 있습니다.

관련 문제