Требуется темплейт кроссплатформенного (win32 + freeBSD) клиент-сервера на Си. Никто не видел? Или может ссылок кто подкинет на сайты по программингу под Unix-системы на Си.
Экзампел нужен клиента + многопоточного сервера (socket, accept, connect, тра-ля-ля), и чтоб компилился как под вин, так и под юникс. Ну там прокси какой нибудь, или чат, или может пример от какой-нибудь книжки. Главное - попроще, я конечно могу mysql качнуть, но там черт ногу сломит. Надо чтоб взять за основу и туда накрутить свою функциональность...
Идея была взять какой нибудь _простой_ готовый код, типа как в экзамплах например Рихтера, когда он байтики гоняет туда-сюда, выкинуть лишнее и вставить свой протокол. И чтоб экзампел кроссплатформенный был. Так как боюсь, что с апачем или с мозиллой я буду дольше разбираться, чем свой с нуля напишу. Ладно, спасибо, посмотрю апач... Нее, там навороченная хрень, типа СУБД, просто хотелось взять быстрый старт
Max тут вам не с 0 стартовать надо. Поищите на gnu или sf готовую либу-оболочку. Да и тут на форуме недавно вопрос был о переносимых интерфейсах СУБД.
клиент: Код (Text): #include <sys/socket.h> #include <sys/types.h> #include <sys/time.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <limits.h> #include <signal.h> #include <netdb.h> int clientSocket = -1; void usage(char *pname) { printf("Usage: %s -p port -s server [-h]\n\tserver by default is '127.0.0.1'\n", pname); } void fsignal(int sig) { switch(sig) { case SIGTERM: case SIGINT: case SIGQUIT: close(clientSocket); exit(0); break; } } int main(int argc, char *argv[]) { unsigned long port = ULONG_MAX, ip = 0; int i, sinLen, ping; char *p, *serv = 0, sbuf[2048]; struct sockaddr_in sockAddr; struct timeval src, buf; struct hostent *he; int avgc, total; if (argc == 1 || argc > 4) { printf("Incorrect count of arguments.\n"); return 0; } for (i = 1; i < argc; i++) { if (argv[i][0] != '-') { printf("All arguments have to start with '-'.\n"); return 0; } switch (argv[i][1]) { case 'h': usage(argv[0]); break; case 'p': port = strtoul(&argv[i][2], &p, 0); if (port == ULONG_MAX || *p != 0) { printf("Incorrect port value. Its have to be number.\n"); } break; case 's': serv = (char *)&argv[i][2]; break; default: printf("Unknown argument. Type -h for help.\n"); return 0; } } // if there is just -h as argument if (port == ULONG_MAX) { printf("Unknown port.\n"); return 0; } if (!serv) serv = "127.0.0.1"; printf("Used port: %d, used server: %s\n", port, serv); for (i = 1; i < 32; i++) signal(i, fsignal); ip = inet_addr(serv); if (ip = INADDR_NONE) { he = (struct hostent *)gethostbyname((const char *)serv); if (!he) return 0; ip = *((unsigned long *)(he->h_addr_list[0])); } clientSocket = socket(AF_INET, SOCK_STREAM, 0); if (clientSocket == -1) return 0; sockAddr.sin_family = AF_INET; sockAddr.sin_addr.s_addr = ip; sockAddr.sin_port = htons((short)port); argc = 0; total = 0; // printf("00000000/00000000"); if (connect(clientSocket, (struct sockaddr *)&sockAddr, sizeof(sockAddr)) == -1) { close(clientSocket); return 0; } while (1){ gettimeofday(&buf, 0); i = recv(clientSocket, sbuf, 2048, 0); if (!i || i == -1) { close(clientSocket); return 0; } gettimeofday(&src, 0); ping = (src.tv_sec - buf.tv_sec) * 1000000 + (src.tv_usec - buf.tv_usec); avgc++; total += ping; // printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b%08d/%08d", total / avgc, ping); // printf("%08d/%08d\n", total / avgc, ping); printf("%08d / %08d\n", total / avgc, ping); } return 0; } севрер: Код (Text): #include <sys/socket.h> #include <sys/types.h> #include <sys/time.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <limits.h> #include <signal.h> int serverSocket = -1; int clientSocket = -1; void usage(char *pname) { printf("Usage: %s -p port [-h]\n", pname); } void fsignal(int sig) { switch(sig) { case SIGTERM: case SIGINT: case SIGQUIT: close(clientSocket); close(serverSocket); exit(0); break; } } int main(int argc, char *argv[]) { unsigned long port = ULONG_MAX; int i, sinLen, delta; char sbuf[2048]; char *p; struct sockaddr_in sockAddr; struct timeval buf, src; if (argc == 1 || argc > 3) { printf("Incorrect count of arguments.\n"); return 0; } for (i = 1; i < argc; i++) { if (argv[i][0] != '-') { printf("All arguments have to begin with '-'.\n"); return 0; } switch (argv[i][1]) { case 'h': usage(argv[0]); break; case 'p': port = strtoul(&argv[i][2], &p, 0); if (port == ULONG_MAX || *p != 0) { printf(""); return 0; } break; default: printf("Unknown option. type -h to show usage.\n"); return 0; } } // if there is just -h as argument if (port == ULONG_MAX) { printf("Put port in arguments.\n"); return 0; } for (i = 1; i < 32; i++) signal(i, fsignal); serverSocket = socket(AF_INET, SOCK_STREAM, 0); if (serverSocket == -1) return 0; sockAddr.sin_family = AF_INET; sockAddr.sin_addr.s_addr = INADDR_ANY; sockAddr.sin_port = htons((short)port); if (bind(serverSocket, (struct sockaddr *)&sockAddr, sizeof(sockAddr)) == -1){ close(serverSocket); return 0; } if (listen(serverSocket, 10) == -1){ close(serverSocket); return 0; } sinLen = sizeof(sockAddr); while ((clientSocket = accept(serverSocket, (struct sockaddr *)&sockAddr, &sinLen)) > 0){ i = fork(); if (i == -1) printf("fork() error.\n"); if (!i) { printf("Client with ip %08X connected.\n", sockAddr.sin_addr.s_addr); do { i = send(clientSocket, sbuf, 2048, 0); if (!i || i == -1) break; } while (1); close(clientSocket); return 0; } printf("Process forked.\n"); } return 0; } работает на линухе, солярке, винде.
всем сенкс, тут более популярно, может кому пригодится: Пишем "ДЕМОНА" своими руками (daemon gcc proccess)
n0name А кто нибудь юзал Dev-C++? Я вот поставил, возникли траблы с компиляцией - даже вышеприведенный пример, требует инклудов, который нет после инсталляции (взять тот же <sys/socket.h>, котрого по дефолту нет, или тот-же <netinet/in.h>, который тянет за собой хренову тучу инклудов). Пробовал переливать инклуды непосредственно с ФриБСД, но они, во-первых, не соответствуют по сруктуре каталогов, а во-вторых, заметно отличаются в размере, что приводит к тому, что компилятор начинает матюкаться. Гуглил всю ночь - тема известная, под винду ответов нет, кто знает, поделитесь опытом - как это дело собрать под Dev-C++??
Max, этот пример в винде неработоспособен (как минимум, нет WSAStartup и есть fork), поэтому он соберётся и будет работать разве что под cygwin-ом. Лучше погугли что-нибудь наподобие «select based server».
Max Я почти всегда при использовании C++ пишу в DevC++. Ну так! Приведенные заголовочники - из *nix, а DevC++ работает под Win. Прямого портирования не получится. Тут нужно смотреть какие структуры/константы/типы используются и какие функции вызываются, искать их в имеющихся либах и те же линковать. Ну или искать порт данных либ под Win. Если будут проблемы - могу посмотреть код сегодня-завтра. Хотя, конечно же, 100% порт невозможен, слишком специфичное приложение пишется ( одна строка "if((parpid=fork())<0)" чего стоит ).
Можно. Но если в *nix fork -- это copy-on-write, то в cygwin -- это копирование всего и сразу. То есть такой форк вешать реакцией на удачный accept не стоит.
r90 Язык тогда неудачно выбран. Стоит задача: Создать клиент и сервак кроссплатформенные. Java, Ada? Почему нет? Задачу решаем средствами, которые для этого предназначены. Если мне закажут драйвер, я же не буду писать его на ассемблере! Так и тут.
а зачем вообще использовать такую специфику? просто написать клиент-сервер в unix-like стиле: многопоточно с блокирующими сокетами. переносимость будет порядка 80% - править оболочку и некоторые моменты сетевой части.
device C -- вполне себе кроссплатформенный язык. Но если представлять себе проблемы не-*nix систем. С учётом специфики windows к созданию процессов надо подходить с опаской. Либо использовать левые библиотеки, либо #ifdef'ы. Либо не использовать процессы вообще.
Народ, вы меня пугаете :-/ Неужто такую банальную вещь нельзя реализовать кроссплатформенно? Как тогда вообще можно говорить о кроссе? Тем более, что n0name написал, что "работает на линухе, солярке, винде". Значит как-то можно? з.ы. C/C++ - требование заказчика
в винде оно может и работает, только из под эмуля какого, как собственно было сказано. варианты: 1. заюзать какую нибуть кросплатформенную либу (напримет QT) 2. написать с нуля , если решишь смотри в сторону winapi функций стандарта posix + #ifdef позволяющие подключить взависимости от платформы сборки нужный хидер. что собственно тоже уже было сказанно ps: а экземплов/демок по кросплатформенному программингу я например не встречал...