#include <winsock.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <string>
#include <fstream>
#include <ctime>
#include "md5.h"
#pragma comment (lib, "ws2_32") 
#pragma comment (lib,"md5.lib")
#define		MAX_CONNECTION_COUNT	2
#define		MAX_FILES_COUNT	 32
#define		MESSAGE_LENGTH			1024 * 64 - 20 - 8 - 33
#define		IP						"192.168.1.2"
#define		PORT					10001
using namespace std;
long sended = 0;
struct sockaddr_in server;
struct threadProcData
{
    sockaddr_in client;
    char response[256];
};
HANDLE mutex;
string files[MAX_FILES_COUNT];
CRITICAL_SECTION CriticalSection[MAX_FILES_COUNT];

void Initialization()
{
    WSADATA WsaDat;
    if (WSAStartup(MAKEWORD(1, 1), &WsaDat) != 0)
        printf("WSA Initialization failed. Error code: %d", WSAGetLastError());
}

SOCKET CreateSocket()
{
    SOCKET sock;
    if (INVALID_SOCKET != (sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)))
    return sock;
    printf("Create socket error. Error code: %d", WSAGetLastError());
    return NULL;
}

void BindSocket(SOCKET sock)
{
    ZeroMemory (&server, sizeof (server));
    server.sin_family = AF_INET;
    server.sin_addr.S_un.S_addr = inet_addr (IP);
    server.sin_port = htons(PORT);
    if (SOCKET_ERROR == bind (sock, (sockaddr* ) &server, sizeof (server)))
        printf("Bind socket error. Error code: %d", WSAGetLastError());
    timeval timeout;
    timeout.tv_sec = 30000;
    timeout.tv_usec = 0;
    int buffsize = MESSAGE_LENGTH;
    //setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,  (char*)&timeout, sizeof(timeout)); 
    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&timeout, sizeof(timeout));
    //setsockopt(sock, SOL_SOCKET, SO_RCVBUF,(const char *)&buffsize, sizeof(buffsize));
}

bool SendData(SOCKET clientSocket,sockaddr_in client,char* serverMessage)
{ 
    if(sendto(clientSocket, serverMessage, strlen(serverMessage), 0, 
        (struct sockaddr *)&client, sizeof(struct sockaddr_in)) != SOCKET_ERROR)
    return true;
    return false;
}

int GetFileInfo(SOCKET Socket, sockaddr_in client, string fileName)
{
    std::ifstream file(fileName, ios::in | ios::binary);
    if (!file.is_open()) 
    {
        SendData(Socket, client, "404 FILE NOT FOUND\r\n\0");
        return 4;
    }
    file.seekg (0, ios::end);
    long readed = file.tellg();
    file.close();
    char tmp[256]; 
    SendData(Socket,client ,(char*)string(ltoa(readed,tmp,10)).c_str());
    return 0;
}

int GetFileDataEx(SOCKET sock,sockaddr_in client, string fileName, long position, int csIndex = 0)
{
    EnterCriticalSection(&CriticalSection[csIndex]);
    std::ifstream file(fileName, ios::in | ios::binary);
    if (!file.is_open()) 
    {
        SendData(sock, client, "404 FILE NOT FOUND\r\n\0");
        return 4;
    }

    char memblock[MESSAGE_LENGTH+1];
    file.seekg (position, ios::beg);
    file.read (memblock, MESSAGE_LENGTH);
    long readed = file.gcount();
    file.close();
    files[csIndex] = string("");
    LeaveCriticalSection(&CriticalSection[csIndex]);
    ReleaseMutex(mutex);

    if(readed > 0)
    {
        char tmp[MESSAGE_LENGTH+33];
        char *tmp2 =strdup(MD5(string(memblock, readed)).hexdigest().c_str());
        for (int i = 0; i < 32; i++) tmp[i] = tmp2[i];
        for (int i = 32; i < readed + 32; i++) tmp[i] = memblock[i-32];
        readed += 32;
        tmp[readed] = '\0';
        if(sendto(sock, tmp, readed, 0,
            (struct sockaddr *)&client, sizeof(struct sockaddr_in)) == SOCKET_ERROR)
        {
            printf("Send socket error. Error code: %d", WSAGetLastError());
            closesocket(sock);
            return 1;
        }
        sended += readed;
        return 0;
    }
    else 
    {
        if(position == 0)
        {
            SendData(sock, client, "404 FILE NOT FOUND\r\n\0");
            return 4;
        }
        SendData(sock, client, "102 ALL SENDED\r\n\0");
        return 1;
    }
    return 0;
}

int GetFileData(SOCKET sock,sockaddr_in client, string fileName, long position)
{
    DWORD waitResult = WaitForSingleObject(mutex,INFINITE);
    if(waitResult == WAIT_OBJECT_0)
    {
        for(int i = 0; i < MAX_FILES_COUNT; i++)
        {
            if(files[i] == fileName)
            {
                files[i] = fileName;
                return GetFileDataEx(sock, client, fileName, position, i);
            }
        }
        return GetFileDataEx(sock, client, fileName, position);
    }
}

int ParseRequest(SOCKET Socket,sockaddr_in client,string message)
{
    if(message.length() < 1) return 4;
    string request[3] = {"","",""};
    int index1 = 0, index2 = 0, i = 0;
    while(1)
    {
        index2 = message.find("\n\r", index2);
        if(index2 > 0 && index2 < message.length())
        {
            request[i] = message.substr(index1 ,index2 - index1);
            index2 += 2;
            index1 = index2;
            i++;
            if(i == 3) break;
        }
        else break;
    }
    if(request[0].compare("GET") == 0)
        return GetFileData(Socket, client,request[1], atol(request[2].c_str()));
    if(request[0].compare("INFO") == 0)
        return GetFileInfo(Socket, client, request[1]);
    else
    {
        SendData(Socket, client, "403 WRONG REQUEST\r\n\0");
        return 4;
    }
    return 0;
}

string ReceiveData(SOCKET Socket, sockaddr_in* client)
{
    char* tmpMessage = new char[MESSAGE_LENGTH];
    int messageLength;	
    int addrLen = (int)sizeof(struct sockaddr_in);
    if ((messageLength = recvfrom(Socket, tmpMessage, MESSAGE_LENGTH, 0, 
        (struct sockaddr *)client, &addrLen)) == -1 )
    {
        printf("Recive message error. Error code: %d\n", WSAGetLastError());
        return string();
    }
    string response(tmpMessage,messageLength);
    delete []tmpMessage;
    return response;
}

DWORD WINAPI ProcessClient(LPVOID param)
{
    sockaddr_in client = ((threadProcData*)param)->client;
    string response = ((threadProcData*)param)->response;
    Initialization();
    SOCKET Socket = CreateSocket();
    
    ZeroMemory (&server, sizeof (server));
    sockaddr_in tmp;
    tmp.sin_family = AF_INET;
    tmp.sin_addr.S_un.S_addr = inet_addr (IP);
    tmp.sin_port = htons(0);
    if (SOCKET_ERROR == bind (Socket, (sockaddr* ) &tmp, sizeof (server)))
        printf("Bind socket error. Error code: %d", WSAGetLastError());
    
    ParseRequest(Socket,client,response);
    while(ParseRequest(Socket,client,ReceiveData(Socket, &client)) == 0);
    closesocket(Socket);
    return 0;
}

int main(int argc, char *argv[])
{
    do
    {
        mutex = CreateMutex(NULL, FALSE, NULL); 
        if (mutex == NULL) 
        {
            printf("CreateMutex error: %d\n", GetLastError());
            return 1;
        }
        for(int i = 0; i < MAX_FILES_COUNT; i++)
        {
            InitializeCriticalSection(&CriticalSection[i]);
        }
        Initialization();
        SOCKET Socket = CreateSocket();
        if(Socket != NULL)
        {
            BindSocket(Socket);
            do
            {
                sockaddr_in client;
                threadProcData t;
                strcpy(t.response,ReceiveData(Socket, &client).c_str()); 
                t.client = client;
                HANDLE thread = CreateThread(NULL,0,&ProcessClient,(LPVOID)&t,0,(LPDWORD)&thread);
            }while(1);
            closesocket (Socket);
        }
        else closesocket (Socket);
        WSACleanup();
    }while(1);
    return 0;
}
Соседние файлы в папке MultiThreadUDPServer
  • #
    15.06.20147.7 Кб45main.cpp
  • #
    15.06.20141.89 Кб45md5.h
  • #
    15.06.20147.14 Кб45MD5.lib
  • #
    15.06.20144.13 Кб46MultiThreadUDPServer.vcxproj
  • #
    15.06.20141.31 Кб45MultiThreadUDPServer.vcxproj.filters
  • #
    15.06.2014143 б45MultiThreadUDPServer.vcxproj.user