// Пример TCP – сервера подсчета указанного символа в полученном тексте #define _CRT_SECURE_NO_WARNINGS 1 #define _WINSOCK_DEPRECATED_NO_WARNINGS #include #include #include // Wincosk2.h должен быть // подключен раньше windows.h! #include // подключение библиотеки #pragma comment(lib,"Ws2_32.lib") #define PORT 666 extern int addLogMessage(const char* text); int ServiceStart(); void ServiceStop(); // макрос для печати количества активных // пользователей char message[256] = { 0 }; #define PRINTNUSERS if(nclients)\ {sprintf(message, "%d user on-line\n", nclients); \ addLogMessage(message); }\ else \ {sprintf(message,"No User on line\n");\ addLogMessage(message); } // прототип функции, обслуживающий // подключившихся пользователей DWORD WINAPI dostuff(LPVOID client_socket); SOCKET mysocket; // глобальная переменная – количество // активных пользователей int nclients = 0; char buff[1024]; // Буфер для различных нужд // функция по варианту int myfunc(char *a, char c) { int total = 0; FILE * hdl; char message[256] = { 0 }; if (hdl = fopen(a, "rt")){ // цикл чтения до конца файла while (!feof(hdl)) { // чтение одного символа из файла if ((char)fgetc(hdl) == c) total++; } // сообщение в консоль sprintf(message,"(Server): file:%s, symbols = %d\n", a, total); addLogMessage(message); // закрытие файла fclose(hdl); } else { // сообщение в канал sprintf(message, "(Server)Can't open %s!", a); strcpy(a, message); total = -1; } return total; } int Server() { sprintf(message,"TCP SERVER DEMO start listen\n"); addLogMessage(message); // Шаг 4 ожидание подключений // размер очереди – 0x100 if (listen(mysocket, 0x100)) { // Ошибка sprintf(message,"Error listen %d\n", WSAGetLastError()); addLogMessage(message); ServiceStop(); return -1; } sprintf(message,"Listen...\n"); addLogMessage(message); // Шаг 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); sprintf(message,"+%s [%s] new connect!\n", (hst) ? hst->h_name : "", inet_ntoa(client_addr.sin_addr)); addLogMessage(message); 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 = (char *)calloc(1024, sizeof(char)); #define str1 "Enter filename up to 1024 bytes\r\n" #define str2 "Enter symbol for counting\r\n" // отправляем клиенту сообщение send(my_sock, str1, sizeof(str1), 0); int bytes_recv, len, lenstr; // размер принятого сообщения char c; // переменные для myfunc char *a = (char *)calloc(1024, sizeof(char)); char bytes[3] = { 0 }; if ((len = recv(my_sock, bytes, 2, 0))>0 && len != SOCKET_ERROR) // принятие длины сообщения от клиента sprintf(message,"Wait %s bytes...\n", bytes); addLogMessage(message); len = atoi(bytes); lenstr = len; if (((bytes_recv = recv(my_sock, buff, len, 0)) == len) && bytes_recv != SOCKET_ERROR) // принятие сообщения от клиента { sprintf(message,"Get %d bytes:%s\n", bytes_recv, buff); addLogMessage(message); strncpy(a, buff, bytes_recv); // копирование текста для освобождения буфера //a[len] = '\n'; ZeroMemory(buff, sizeof(buff)); send(my_sock, str2, sizeof(str2), 0); // отправляем клиенту сообщение } // обработка второго параметра ZeroMemory(bytes, sizeof(bytes)); bytes_recv = 0; if ((len = recv(my_sock, bytes, 2, 0)) > 0 && len != SOCKET_ERROR) // принятие длины сообщения от клиента { sprintf(message, "Wait %s byte(s)...\n", bytes); addLogMessage(message); } len = atoi(bytes); lenstr = len; if ((bytes_recv = recv(my_sock, buff, len, 0) >0) && bytes_recv != SOCKET_ERROR) // принятие сообщения от клиента { sprintf(message,"Get char:%s\n", buff); //символ для подсчета addLogMessage(message); c = buff[0]; // len = myfunc(a, c); // вызов пользовательской функции ZeroMemory(buff, sizeof(buff)); itoa(len, bytes, 10); // преобразование результата выполнения в строку if (len >= 0) { strcpy(buff, "Answer:"); strcat(buff, bytes); } else strcat(buff, a); buff[strlen(buff)] = '\n';// '\n'; // добавление к сообщению символа конца строки ZeroMemory(message, sizeof(message)); sprintf(message,"Server:%s\n", buff); addLogMessage(message); buff[strlen(buff) + 1] = '\r'; send(my_sock, buff, strlen(buff), 0); // отправляем клиенту результат } nclients--; // уменьшаем счетчик активных клиентов sprintf(message,"-disconnect\n"); addLogMessage(message); PRINTNUSERS // закрываем сокет closesocket(my_sock); return 0; } int ServiceStart() { // Шаг 1 - Инициализация Библиотеки Сокетов if (WSAStartup(0x0202, (WSADATA *)&buff[0])) { // Ошибка! sprintf(message,"Error WSAStartup %d\n", WSAGetLastError()); addLogMessage(message); return -1; } // Шаг 2 - создание сокета //SOCKET mysocket; // AF_INET - система адресации // SOCK_STREAM - потоковый сокет (TCP) // 0 - по умолчанию выбирается TCP протокол if ((mysocket = socket(AF_INET, SOCK_STREAM, 0))<0) { // Ошибка! sprintf(message,"Error socket %d\n", WSAGetLastError()); addLogMessage(message); 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))) { // обработка ошибка sprintf(message,"Error bind %d\n", WSAGetLastError()); addLogMessage(message); closesocket(mysocket); // закрываем сокет! WSACleanup(); return -1; } } void ServiceStop() { // закрываем сокет sprintf(message, "TCP SERVER DEMO stopping...\n"); addLogMessage(message); closesocket(mysocket); WSACleanup(); }