// Пример простого TCP – сервера #include #include #include // Wincosk2.h должен быть // подключен раньше windows.h! #include #define PORT 666 // макрос для печати количества активных // пользователей #define PRINTNUSERS if(nclients)\ printf("%d user on-line\n",nclients);\ else printf("No User on line\n"); // прототип функции, обслуживающий // подключившихся пользователей DWORD WINAPI dostuff(LPVOID client_socket); // глобальная переменная – количество // активных пользователей int nclients = 0; // функция по варианту int myfunc(int a, int b) { return a+b; } int main(int argc, char* argv[]) { char buff[1024]; // Буфер для различных нужд printf("TCP SERVER DEMO\n"); // Шаг 1 - Инициализация Библиотеки Сокетов // Т.к. возвращенная функцией информация // не используется ей передается указатель на // рабочий буфер, преобразуемый // к указателю на структуру WSADATA. // Такой прием позволяет сэкономить одну // переменную, однако, буфер должен быть не менее // полкилобайта размером (структура WSADATA // занимает 400 байт) if (WSAStartup(0x0202,(WSADATA *) &buff[0])) { // Ошибка! printf("Error WSAStartup %d\n", WSAGetLastError()); return -1; } // Шаг 2 - создание сокета SOCKET mysocket; // AF_INET - система адресации // SOCK_STREAM - потоковый сокет (TCP) // 0 - по умолчанию выбирается TCP протокол if ((mysocket=socket(AF_INET,SOCK_STREAM,0))<0) { // Ошибка! printf("Error socket %d\n",WSAGetLastError()); WSACleanup(); // Деиницилизация библиотеки Winsock return -1; } // Шаг 3 связывание сокета с локальным адресом sockaddr_in local_addr; local_addr.sin_family=AF_INET; // задание системы адресации local_addr.sin_port=htons(PORT); // задние порта local_addr.sin_addr.s_addr=INADDR_ANY; // сервер принимает подключения // на все IP-адреса // вызываем bind для связывания if (bind(mysocket,(sockaddr *) &local_addr,sizeof(local_addr))) { // обработка ошибка printf("Error bind %d\n",WSAGetLastError()); closesocket(mysocket); // закрываем сокет! WSACleanup(); return -1; } // Шаг 4 ожидание подключений // размер очереди – 0x100 if (listen(mysocket, 0x100)) { // Ошибка printf("Error listen %d\n",WSAGetLastError()); closesocket(mysocket); WSACleanup(); return -1; } printf("Listen...\n"); // Шаг 5 извлекаем сообщение из очереди SOCKET client_socket; // сокет клиента sockaddr_in client_addr; // адрес клиента // (заполняется системой) // функции accept необходимо передать размер структуры int client_addr_size=sizeof(client_addr); // цикл извлечения запросов на подключение из очереди while((client_socket=accept(mysocket, (sockaddr *) &client_addr, &client_addr_size))) { nclients++; // увеличиваем счетчик // подключившихся клиентов // вывод сведений о клиенте HOSTENT *hst; hst=gethostbyaddr((char *)&client_addr.sin_addr.s_addr,4, AF_INET); printf("+%s [%s] new connect!\n", (hst)?hst->h_name:"", inet_ntoa(client_addr.sin_addr)); PRINTNUSERS // Вызов нового потока для обслужвания клиента DWORD thID; CreateThread(NULL,NULL,dostuff,&client_socket,NULL,&thID); } return 0; } // Эта функция создается в отдельном потоке и // обсуживает очередного подключившегося клиента // независимо от остальных DWORD WINAPI dostuff(LPVOID client_socket) { SOCKET my_sock; my_sock = ((SOCKET *)client_socket)[0]; char buff[20 * 1024]; #define str1 "Enter 1 parametr\r\n" #define str2 "Enter 2 parametr\r\n" // отправляем клиенту сообщение send(my_sock, str1, sizeof(str1), 0); int bytes_recv; // размер принятого сообщения int a,b; // переменные для myfunc // обработка первого параметра if((bytes_recv = recv(my_sock,&buff[0],sizeof(buff),0)) && bytes_recv != SOCKET_ERROR) // принятие сообщения от клиента { a = atoi(buff); // преобразование первого параметра в int send(my_sock,str2,sizeof(str2),0); // отправляем клиенту сообщение } // обработка второго параметра if((bytes_recv = recv(my_sock,&buff[0],sizeof(buff),0)) && bytes_recv != SOCKET_ERROR) // принятие сообщения от клиента { b = atoi(buff); // преобразование второго параметра в int a = myfunc(a,b); // вызов пользовательской функции itoa(a,buff,10); // преобразование результата выполнения в строку buff[strlen(buff)] = '\n'; // добавление к сообщению символа конца строки send(my_sock,&buff[0],bytes_recv,0); // отправляем клиенту результат } nclients--; // уменьшаем счетчик активных клиентов printf("-disconnect\n"); PRINTNUSERS // закрываем сокет closesocket(my_sock); return 0; }