Я новичок здесь (мой первый вопрос) и немного нового, у меня никогда не было классов программирования, поэтому ... извините за какой-то хаотичный код.Отправка файлов через сокеты слишком медленно
Я сделал эту программу, которая отправляет (клиент) и получает (сервер) файлы через сокеты, клиент считывает и отправляет 1024 байта файла за цикл, а сервер его получает и записывает в файл. Он работает нормально, но проблема в том, что он очень медленный. Это занимает столько времени, что отправляет файл с моего компьютера на компьютер как отправку на другой компьютер, но все равно занимает больше времени, чем ожидалось, когда я пытаюсь передать, например, через skype, это намного быстрее. Любая подсказка? (Ниже приведен код, который я использую).
Сервер:
// 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;
}
Клиент:
// 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 на окнах 7.
Цените любую помощь, а также дайте мне знать, если есть что-то неправильно со структурой этого вопроса.
Первое - ваш размер буфера составляет всего 512 байт, что очень мало. Просто попробуйте изменить его на 65536 и посмотреть, какой эффект он имеет. Существует некоторый физический размер, который наиболее подходит, если это помогает ... –
Просто попробовал и не имеет никакого эффекта. – user2220419
Вы изменили свой 'send', чтобы читать и отправлять более 1024 байтов за раз, правильно? –