私はここで初めて(私の最初の質問)であり、少し初心者です。プログラミングクラスを受講したことがないため、混沌としたコードで申し訳ありません。
ソケットを介してファイルを送信 (クライアント) および受信 (サーバー) するこのプログラムを作成しました。クライアントはループごとに 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;
}
Windows 7 で Visual Studio 2010 を使用しています。
この質問の構造に何か問題があるかどうかも教えてください。