/* Глава 12. commands.с. */
/* Команды внутрипроцессного сервера для использования в serverSK и так далее. */
/* Имеется несколько команд, реализованных в виде библиотек DLLs. */
/* Функция каждой команды принимает два параметра и обеспечивает */
/* безопасное выполнение в многопоточном режиме. Первым параметром */
/* является строка: команда arg1 arg2 … argn */
/* (то есть обычная командная строка), а вторым – имя выходного файла. … */
static void extract_token(int, char *, char *);
_declspec(dllexport)
int wcip(char * command, char * output_file)
/* Счетчик слов; внутрипроцессный. */
/* ПРИМЕЧАНИЕ: упрощенная версия; результаты могут отличаться от тех, которые обеспечивает утилита wc. */
{
extract_token(1, command, input_file);
fin = fopen(input_file, "r");
/* … */
ch = nw = nc = nl = 0;
while ((c = fgetc(fin)) != EOF) {
/* … Стандартный код — для данного примера не является существенным … */
}
fclose(fin);
/* Записать результаты. */
fout = fopen(output_file, "w");
if (fout == NULL) return 2;
fprintf(fout, " %9d %9d %9d %s\n", nl, nw, nc, input_file);
fclose(fout);
return 0;
}
_declspec(dllexport)
int toupperip(char * command, char * output_file)
/* Преобразует входные данные к верхнему регистру; выполняется внутри процесса. */
/* Вторая лексема задает входной файл (первая лексема – "toupperip"). */
{
/* … */
extract_token(1, command, input_file);
fin = fopen(input_file, "r");
if (fin == NULL) return 1;
fout = fopen(output_file, "w");
if (fout == NULL) return 2;
while ((c = fgetc (fin)) != EOF) {
if (c == '\0') break;
if (isalpha(c)) с = toupper(c);
fputc(c, fout);
}
fclose(fin);
fclose(fout);
return 0;
}
static void extract_token(int it, char * command, char * token) {
/* Извлекает из "команды" лексему номер "it" (номером первой лексемы */
/* является "0"). Результат переходит в "лексему" (token) */
/* В качестве разделителей лексем используются пробелы. … */
return;
}
Ориентированные на строки сообщения, точкив хода DLL и TLS
Программы serverSK и clientSK взаимодействуют между собой, обмениваясь сообщениями, каждое из которых состоит из 4-байтового заголовка, содержащего размер сообщения, и собственно содержимого. Обычной альтернативой такому подходу служат сообщения, отделяемые друг от друга символами конца строки (или перевода строки).
Трудность работы с такими сообщениями заключается в том, что длина сообщения заранее не известна, в связи с чем приходится проверять каждый поступающий символ. Однако получение по одному символу за один раз крайне неэффективно, и поэтому символы сохраняются в буфере, содержимое которого может включать один или несколько символов конца строки и составные части одного или нескольких сообщений.