пере мной "встала" задача, да сиго нечего подобного не писал так как установленных средств разработки был только Builder6 псиал на нем. Вот условие: Необходимо организовать надежную передачу файлов между двумя узлами сети . Клиент соединяется с сервером по консольной команде connect [servemame ]: [port ]. После этого пользователь может запросить у сервера получение любого файла, находящегося в рабочем каталоге сервера с помощью команды get [filename ]. Сервер разбивает файл на датаграммы, и отправляет их клиенту. Клиент собирает файл из полученных датаграмм в своем рабочем каталоге. Затем, при получении всего файла, открывает его с помощью CreateProcess И команды "start filename". Для решения задачи с использованием протокола TCP также требуется разработать протокол обмена, но главной сложностью будет являться определение границ передаваемых сообщений, поскольку надежность и порядок доставки обеспечивает сам протокол. Кроме того, немаловажным будет обеспечить устойчивую работу сервера при отключении / ошибках клиентов. Сервер должен поддерживать одновременную работу с 254 клиентами. все что сумел это написать не смог, вернее не понимаю принцип заполнения буфера при чтении файла отправление его по сокету и получение и запись на стороне клиента Код прилагается: Сервер: -------------------------------------------------------------------------- //--------------------------------------------------------------------------- #include "stdio.h" #include <winsock2.h> #include <conio.h> #include <vcl.h> #pragma hdrstop #include "iostream.h" //--------------------------------------------------------------------------- #pragma argsused // размер буфера приемника передачика const UINT BUF_SIZE = 256; // структура для передачи функции параметров потока struct SessionParam { SOCKET acceptSocket; int clientNum; }; // потока облуживания клиента DWORD WINAPI SessionThread( LPVOID lpParam ) { SessionParam sp = *(SessionParam*)lpParam; delete lpParam; printf( "Start session %d\n", sp.clientNum) ; int bytesSent, bytesRecv; // кол-во переданных принятых байт char sendbuf[BUF_SIZE]; // буфер передачи char recvbuf[BUF_SIZE]; // буфер приема char bufferRead[BUF_SIZE]; // oeee recv-send while (1) { // принимаем даннные клиента bytesRecv = recv( sp.acceptSocket, recvbuf, 255, 0 ); if (bytesRecv == SOCKET_ERROR) break; printf( "\tSession %d, bytes recived: %ld\n", sp.clientNum, bytesRecv ) ; if (bytesRecv == 0) break; //------------------------------------------------------------------------------ int FileNam=0; //куча объявлений)))) int nam,a,b; LPCTSTR lpFileName; LPCTSTR lpFileName1; AnsiString Str1; AnsiString Str2; AnsiString D="1.txt"; //char D; AnsiString DriveStrings; DWORD dwBytes; //aooa? char buf[32]; BOOL bResult,bResultWrite; DWORD dwBytes1; DWORD Folder; DWORD File; DWORD FolNam; HANDLE hFndF,hFileRecv,hFileRecv1; //oeacaoaeu WIN32_FIND_DATA FindFile; TCHAR lpBuffer[MAX_PATH]; //scanf("%s\n",D.c_str()); DWORD nBufferLength; GetCurrentDirectory(sizeof(lpBuffer),lpBuffer); printf("%s\n",lpBuffer); Str1=lpBuffer+String("\\RecvFile\\*.*"); printf("%s\n",Str1); hFndF=FindFirstFile(Str1.c_str(), &FindFile); lpFileName=FindFile.cFileName; if (hFndF!=INVALID_HANDLE_VALUE){ do{ Folder=FindFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; if (AnsiString(FindFile.cFileName)!=".") if (AnsiString(FindFile.cFileName)!=".."){ { if (!Folder){ if (strcmp(D.c_str(),FindFile.cFileName)==0){ Str1=lpBuffer+String("\\RecvFile\\")+FindFile.cFileName; hFileRecv= CreateFile( Str1.c_str(), // pointer to name of the file GENERIC_READ, // access (read-write) mode FILE_SHARE_READ, // share mode NULL, // pointer to security attributes OPEN_EXISTING, // how to create FILE_ATTRIBUTE_NORMAL, // file attributes NULL // handle to file with attributes to copy ); hFileRecv1= CreateFile( // OpenFile "1.txt", // pointer to name of the file GENERIC_WRITE, // access (read-write) mode NULL, // share mode NULL, // pointer to security attributes CREATE_ALWAYS, // how to create FILE_ATTRIBUTE_NORMAL, // file attributes NULL // handle to file with attributes to copy ); do{ bResult=ReadFile ( hFileRecv, // aane?eioi? ioe?uoiai oaeea &bufferRead, // oeacaoaeu ia aooa?, a eioi?ue 16, // ?eoaai ii 1 aaeoo &dwBytes, // eie-ai ?aaeuii n?eoaiiuo aaeo NULL); send( sp.acceptSocket, bufferRead, strlen(bufferRead)+1, 0 ); ВОТ ЗДЕСЬ начинаются траблы bResultWrite= WriteFile(hFileRecv1, // handle to file to write to &bufferRead, // pointer to data to write to file dwBytes, // number of bytes to write &dwBytes1, // pointer to number of bytes written NULL // pointer to structure needed for overlapped I/O ); } while(dwBytes1>0); CloseHandle(hFileRecv1); DriveStrings=Str2.c_str(); printf("%s\n",Str2); } FileNam=FileNam+1; printf("%s\n",&FindFile.cFileName); } } } } while (FindNextFile(hFndF,&FindFile)!=0); } printf("Tolal File: %d\n",FileNam); //------------------------------------------------------------------------------ // CopyMemory(sendbuf, recvbuf, bytesRecv); // ionueaai ?acoeuoaoa ia?aoii eeeaioo bytesSent = send( sp.acceptSocket, sendbuf, bytesRecv, 0 ); if (bytesSent == SOCKET_ERROR) break; printf("tSession %d, bytes send: %ld\n",sp.clientNum,bytesSent); } printf( "End session %d\n", sp.clientNum) ; return 0; } // noa?oiaay ooieoey aey iioiea - // oaaeii aey nicaaiey iiaiai iioiea SessionThread void SessionThreadStart( SOCKET acceptSocket, int clientNum ) { SessionParam* sp = new SessionParam; sp->acceptSocket = acceptSocket; sp->clientNum = clientNum; // nicaaai iiaue iioie-nanne? HANDLE hThread = CreateThread( NULL, 0, SessionThread, (PVOID)sp, 0, NULL) ; CloseHandle(hThread) ; // e n?aco ?a cae?uaaai aai aane?eioi? } // aeaaiue iioie na?aa?a int _tmain(int argc, _TCHAR* argv[]) { // Eieoeaeecaoey nieaoia WSADATA wsaData; int iResult = WSAStartup( MAKEWORD(2,2), &wsaData ); if ( iResult != NO_ERROR ) { printf("Error at WSAStartup()\n"); _getch(); return -1; } // Nicaaiea iiaiai ON?-nieaoa SOCKET m_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if ( m_socket == INVALID_SOCKET ) { printf( "Error at socket!): %ld\n", WSAGetLastError()); WSACleanup() ; _getch(); return -1; } /* BOOL so_reuse = TRUE; setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&so_reuse, sizeof(BOOL) */ // I?eaycea (binding) nieaoa e aa?ano e ii?oo sockaddr_in service; service.sin_family = AF_INET; service.sin_addr.s_addr = inet_addr( "127.0.0.1" ); service.sin_port = htons( 27015 ); if ( bind( m_socket, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR) { printf( "bind() failed: %ld\n", WSAGetLastError()); closesocket(m_socket) ; WSACleanup(); _getch(); return -1; } // ia?aaiaei nieao a "neooa?uee" ?a?ei if ( listen( m_socket, SOMAXCONN ) == SOCKET_ERROR ) { printf( "Error listen() on socket.\n"); closesocket(m_socket ); WSACleanup(); _getch(); return -1; } int clientNum = 0; // aaneiia?iue oeee ianeo?eaaiey eeeaioia while (1) { printf( "Waiting for next client to connect...\n" ); // "eiiey" nieaoa m_socket - nicaaaony ooieoeae accept SOCKET acceptSocket = SOCKET_ERROR; // i?eieiaai connect'u eeeaioia ... while (acceptSocket == SOCKET_ERROR) { // ... nicaaaay eiiee enoiaiiai nieaoa acceptSocket = accept( m_socket, NULL, NULL ); } printf( "Client %d is connected\n", ++clientNum) ; // nicaaai iiaue iioie, ?aaioa?uee n eeeaioii SessionThreadStart( acceptSocket, clientNum ) ; } // caaa?oaiea ?aaiou na?aa?a closesocket(m_socket); WSACleanup() ; // ?aai aaiaa iieuciaaoaey _getch(); return 0; } //------------------------------------------------------------------------
код клиента: int main(int argc, char* argv[]) { // return 0; //} // eia i?ia?aiiu-eeeaioa //int _tmain(int argc, _TCHAR* argv[]) //{ // Eieoeaeecaoey nieaoia WSADATA wsaData; int iResult = WSAStartup( MAKEWORD(2,2), &wsaData ); if ( iResult != NO_ERROR ) printf("Error at WSAStartup()\n"); // Nicaaiea nieaoa SOCKET m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP ); if ( m_socket == INVALID_SOCKET ) { printf( "Error at socket!): %ld\n", WSAGetLastError()); WSACleanup() ; return -1; } /* BOOL so_reuse = TRUE; setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&so_reuse, sizeof(BOOL)) */ // Nicaaiea niaaeiaiey n na?aa?ii "127.0.0.1" /* char ip_address[10]; char a[10]; printf("Connect [ip_address]: "); gets(ip_address); printf("\n"); printf(" [port]: "); DWORD port; scanf("%d",&port); printf("\n"); */ sockaddr_in clientService; clientService.sin_family = AF_INET; clientService.sin_addr.s_addr = inet_addr("127.0.0.1"); clientService.sin_port = htons( 27015 ); if ( connect(m_socket, (SOCKADDR*)&clientService, sizeof(clientService) ) == SOCKET_ERROR) { printf( "Failed to connect.\n" ); closesocket(m_socket); WSACleanup() ; return -1; } // aaneiia?iue oeee ia?aaa?e/i?eaia aaiiuo while (1) { // Send and receive data. int bytesSent; // ?enei iineaiiuo aaeo int bytesRecv = SOCKET_ERROR; // ?enei i?eiyouo aaeo char sendbuf[BUF_SIZE]; // aooa? ia?aaa?e char recvbuf[BUF_SIZE]; // aooa? i?eaia // iieo?aai no?ieo io iieuciaaoaey printf("Please enter some text: "); gets(sendbuf); if (lstrcmpi(sendbuf, "quit") == 0) break; // ia?aaaai no?ieo na?aa?o bytesSent = send(m_socket, sendbuf, strlen(sendbuf)+1, 0 ); printf( "Bytes Sent: %ld\n", bytesSent ); // oeee i?eaia aaiiuo while(bytesRecv==SOCKET_ERROR){ bytesRecv=recv(m_socket,recvbuf,32,0); if ( bytesRecv == 0 || bytesRecv == WSAECONNRESET ) { printf( "Connection Closed.\n"); break; } if (bytesRecv < 0) return -1; printf( "Bytes Recv: %ld\n", bytesRecv ); } printf( "Server say: %s\n", recvbuf ); } // caaa?oaiea ?aaiou eeeaioa int err = closesocket( m_socket ); if ( err == SOCKET_ERROR ) { printf ("Error closing socket!"); WSACleanup() ; _getch(); } return 0; } добавлено через 7 минут бытесРецв=рецв(м_соцкет,рецвбуф,32,0); бытесСент = сенд(м_соцкет, сендбуф, стрлен(сендбуф)+1, 0 ); вопросы 1)как работает передача\ прием 2)как как реализовать контроль целосности передоваемого файла 3)...еще там в коде сервера при чтении из файла, нужно условие "конца файла" Р.С. в клиенте нет кода на создание файла и запись в него, он лежит в сервере там где и чтение добавлено через 9 минут bytesSent = send(m_socket, sendbuf, strlen(sendbuf)+1, 0 ); bytesRecv=recv(m_socket,recvbuf,32,0); чертов транслит:frustrate
Используй фтп. В каждой операционке есть клиент. По программированию: Обычно функции считывающие из сокета (или любого другого потока) возвращают число реально скачаных байт или -1 если больше ничего нет. TCP сам заботиться о гарантии (и порядке) доставки пакетов. В крайнем случае можно писать сначала в поток длинну файла, а затем сам файл. На клиенте в том же порядке читается сначала длина и потом файл (с уже известной длиной).
есть код правда на дельфи по пересылке файлов.Могу кинуть Я сначала там создавал и отправлял управляющуюю посылку, а потом взависимости оот нее либо передал клиенту файл,либо забирал
BOOL TransmitFile( SOCKET hSocket, HANDLE hFile, DWORD nNumberOfBytesToWrite, DWORD nNumberOfBytesPerSend, LPOVERLAPPED lpOverlapped, LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, DWORD dwFlags ); вот нашел функцию интереснуютеперь не могу корекно ей воспользоваться.... как на сторане клиента, узнать что файл передан? нет, мне надо на С++ самому написать...религия не велит(