Поиск  Пользователи  Правила 
Закрыть
Логин:
Пароль:
Забыли свой пароль?
Войти
 
Страницы: 1 2 След.
RSS
Пример сервера на С
 
Может кто нибудь привести наиболее компактный пример сервера прослушивающий определённый порт? В интеренете все примеры очень перегружены _мусором_, в книге примёр приведён под win, а хочется просто понять как всё работает и чего можно выбросить. Как вижу программу я: bind(), listen(), accept(). Никаких других наворотов вроде не надо, но мой код который должен выполнять эти функции не работает (порт не прослушиватеся). Помогите пожалуйста.
 
bind, listen, после чего ставится бесконечный цикл и ожидание запросов. При получении делается accept и создание нового треда/процесса с передачей дескриптора сокета для обработки.
Вообще, хорошая статья тут
 
Вот что получилось:
Код
int main()
{
struct sockaddr_in local;
local.sin_family = PF_INET;
local.sin_addr.s_addr = htonl(INADDR_ANY);
local.sin_port = htons(1335);
int lclsock;
lclsock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(!lclsock)
{
fprintf(stderr, "Cannot create socket!\n");
_Exit(-1);
}
bind(lclsock, (struct sockaddr *)&local, sizeof(local));
listen(lclsock, 2);
accept(lclsock, 0, 0);
return 0;
}


Теперь интересует собственно сам клиент. Как должно происходить взаимодействие - как например сделать так чтобы получая от клиента helo сервер отвечал ему что либо, а получая quit закрывал соединение? Буду признателен за любую помощь!
 
Буду признателен за ссылки по этой теме.
 
Ссылка

Вообще, самый простой вариант:

1) получил строку
2) конструкция типа switch() её разбирает и делает дальнейшие действия (выплёвывает ответ, закрывает соединение и т.п.)
 
Спасибо за ответ, етсь несколько вопросов:
1) Как мы знаём когда поступает коннект? Сразу после accept() вызвать  recv()?
пример:
Код
accept(mysck, 0, 0);
char * request; request = (char *)calloc(BUSIZ, sizeof(char));
recv(mysck, request, BUFSIZ, 0);
switch(request):
....

Так?
2) Завершить соединение с клиентом? Какой вызов для этого используется?
 
почти...
далее, поулчить и посылать данные нужно уже тому сокету, который accept() возвратит...
соответственнго, нужно проверить, вернул ли он что либо.
закрыть соединение - close(); - в качестве параметра тот сокет, котоый вернул accept
обычно, если не изменяет памятьЮ, структура такая...
while(cs=accept(...))
{
if(fork()==0)
{ //дитеныш, а родитель продолжает слушать сокет
читаем и пишем в cs
close(cs);
exit; /по идее, иили че там, чтоб закрыть проуесс..
}

}
--------
если не разберешся, могу простенький сервер накатать, как время станет...
 
кстати, в сте\атье, приведенной ^rage^, есть неплохой прием, с заранее созданным некотором количеством процессов.
Так, чтобы каждый раз форками не загромаждать....
 
пул форков - эт конечно неплохо, но лично я вообще против создания процессов. пул тредов мне нравится больше.
 
Почти сделал (спасибо Phoenix):
Код
int main()
{
struct sockaddr_in  local;
memset(&local, '\0', sizeof(local));
local.sin_family = PF_INET;
local.sin_addr.s_addr = htonl(INADDR_ANY);
local.sin_port = htons(31337);
int mysck; mysck = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(!mysck)
{
fprintf(stderr, "Cannot create socket!!\n");
_Exit(-1);
}
bind(mysck, (struct sockaddr *)&local, sizeof(local));
listen(mysck, 2);
char clientreq[BUFSIZ];
int clientsock; clientsock = accept(mysck, 0, 0);
recv(clientsock, clientreq, BUFSIZ, 0);
if(clientreq == "q") close(clientsock);
return 0;
}

Вот только тепрь при telnet localhost 31337 не только на q но и на любые запросы сервер закрывает соединение. Почему?
 
ответ - потому что, в любом случае идет return 0, который вырубает сервер, и следовательно, соединение завершается...
 
теперь берем за основу твой пример, и пообтесываем его...
Код
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>


#define BUFSIZ 1024&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 

int main()
{
 struct sockaddr_in local;
 memset(&local, '\0', sizeof(local));
 local.sin_family = PF_INET;
 local.sin_addr.s_addr = htonl(INADDR_ANY);
 local.sin_port = htons(31337);
 int mysck; mysck = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
 if(!mysck)
 {
&nbsp;&nbsp;&nbsp;fprintf(stderr, "Cannot create socket!!\n");
  _Exit(-1);
 }
 
 bind(mysck, (struct sockaddr *)&local, sizeof(local));
 listen(mysck, 2);
 char clientreq[BUFSIZ];
 int clientsock; 
 while(1) 
 // все таки, делаем так, чтоб по окончания соединяния, сервер не умер
 // однако, если интерестно, то можно и закомментарить while(1) 
 if(clientsock = accept(mysck, 0, 0))
 {
&nbsp;&nbsp;&nbsp;int ok=1;
&nbsp;&nbsp;&nbsp;while(ok) // работаем с клиентом, пока он сам не закрыл соединение, либо пока не прозошла какая нить ошибка...
&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int co;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;co=recv(clientsock, clientreq, BUFSIZ, 0);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(co==-1)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ok=0; //error
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(co>0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(clientreq[0] == 'q') //если первая буква в команде от клиенте ==q (ты сравнивал адреса, что вообще говоря, безссмысленно. Для сравнения строк можно юзать strcpy и тп)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  close(clientsock);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  ok=0;&nbsp;&nbsp;&nbsp;// тогда закрываем клиентский сокет и говорим, что больше работать с клиентом не надо
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;  else send(clientsock, "not found\n", 10, 0); // при любой другой команде говорим клинету, что команда не найден
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;}
 }
 return 0;
} 
 
далее, смотрим, как все это работает
Код
-bash-2.05b$ telnet localhost 31337
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
sdfasf
not found
asdfasd
not found
fasdf
not found
qwdf
Connection closed by foreign host.
-bash-2.05b$ 
В эжто время в другой терминалке
-bash-2.05b$ telnet localhost 31337
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
sadfasf
asfa
sdf
sdf (вырубае первую терминалку)
not found
qwe
Connection closed by foreign host.

видим, что во второй терминалке сервер начал нормально обрабатывать ответы, тоьлко после завершения первого сеанса...
что делать, чтобы этого не было....
 
в общем.Ю вот че у меня получилось...
Код
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>


#define BUFSIZ 1024&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 

int main()
{
 struct sockaddr_in local;
 memset(&local, '\0', sizeof(local));
 local.sin_family = PF_INET;
 local.sin_addr.s_addr = htonl(INADDR_ANY);
 local.sin_port = htons(31337);
 int mysck; 
 mysck = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
 if(!mysck)
 {
&nbsp;&nbsp;&nbsp;fprintf(stderr, "Cannot create socket!!\n");
  _Exit(-1);
 }
 
 bind(mysck, (struct sockaddr *)&local, sizeof(local));
 listen(mysck, 2);
 char clientreq[BUFSIZ];
 int clientsock; 
 while(1) 
 if(clientsock = accept(mysck, 0, 0))
 {
&nbsp;&nbsp;&nbsp;if(fork()==0) // все тоже самое, тока всю работу с клиентом проводит дочерний процесс
&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int ok=1;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close(mysck); // дочеренму процессу не нужен дескриптор основного сокета
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(ok) //беседуем
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int co;
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;co=recv(clientsock , clientreq, BUFSIZ, 0);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(co==-1)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ok=0; //error
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(co>0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  if(clientreq[0] == 'q')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  { 
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;ok=0;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  }
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  else send(clientsock, "not found\n", 10, 0);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}// of while
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;send(clientsock, "good bye\n", 9, 0); 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close(clientsock); //это  я сюда перенес, на самом деле, пофиг..
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(0); //заверщает дите
&nbsp;&nbsp;&nbsp;}//of fork
&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;{ //это родитель
&nbsp;&nbsp;&nbsp;&nbsp;close(clientsock); // родителю не нужен дескриптор клиентского сокета
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// далее, родитель продолжает работать, принимать соединения.
&nbsp;&nbsp;&nbsp;}
 }
 return 0;
} 

При таком раскаладе, паралельно с сервером может работать любое число клиентов....
вроде все понятною.... тока вот чета у меня вот такими какашками зосоряется список процессов
Код
-bash-2.05b$ ps -aux | grep s3
admin&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0  0.0  0.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;0  p1  ZW+  -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0:00.00  (s3)
admin&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0  0.0  0.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;0  p1  ZW+  -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0:00.00  (s3)
admin&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0  0.0  0.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;0  p1  ZW+  -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0:00.00  (s3)
admin&nbsp;&nbsp;&nbsp;41612  0.0  0.1  1176  468  p1  I+&nbsp;&nbsp;&nbsp;&nbsp;6:08PM&nbsp;&nbsp;&nbsp;0:00.00 ./s3
admin&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0  0.0  0.0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;0  p1  ZW+  -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0:00.00  (s3)

мож кто подскажет, что не так?
в остальном все работаетю....
 
Я думал Phoenix задал вопрос, о том, что надо исправить для того, чтобы blowfish напряг мозги...А ок. что-то P незнает.

Это нужно SIGCHILD обрабытывать, там в цикле waitpid делать, вот зомби и висят-то.

Код
#include<signal.h>
#include<unistd.h>
#include<sys/wait.h>

void handler()
{
  while (waitpid(-1, NULL, WNOHANG) > 0)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;; /* null operator*/
}
.......
int main()
{
&nbsp;&nbsp;&nbsp;&nbsp;struct sigaction sa;
&nbsp;&nbsp;&nbsp;&nbsp;memset(&sa, '\0', sizeof(struct sigaction));
&nbsp;&nbsp;&nbsp;&nbsp;sa.sa_handler = handler;
&nbsp;&nbsp;&nbsp;&nbsp;sa.sa_flags = 0;
&nbsp;&nbsp;&nbsp;&nbsp;sigaction(SIGCHLD, &sa, NULL);
.......
&nbsp;&nbsp;&nbsp;&nbsp;return 0;
}

 
2 MishaSt
да, не, честно не знал :)
как то давно очень я на Си под юникс программил и мало...
 
Я что то упустил, код работает но сразу же закрывает соединение и завершает процесс:
Код
int main(int argc, char ** argv)
{
struct sockaddr_in local;
memset(&local, '\0', sizeof(local));
local.sin_family = PF_INET;
local.sin_addr.s_addr = htonl(INADDR_ANY);
local.sin_port = htons(3333);
int mysck; mysck = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if(!mysck)
{
perror("Cannot create socket!\n");
_Exit(-1);
}
int cs; char cr[BUFSIZ];
bind(mysck, (struct sockaddr *)&local, sizeof(local));
listen(mysck, 2);
cs = accept(mysck, 0, 0);
int ok = 1;
int stat;
while(ok)
{
stat = recv(cs, cr, BUFSIZ, 0);
if(cr[0] != 'q')
{
send(cs, "Error\n\n", 10, 0);
}
else close(cs); ok = 0;
}
close(mysck);
return 0;
}
 
Уважаемый автор поста.

Я настоятельно рекомендую почитать популярные книги по
BSD SOCKET API а так же почитать маны той, системы, на которой вы желаете программировать.
Рекомендую книгу "Сети TCP/IP том 3. Разработка приложений типа клиент/сервер для Linux/POSIX "
Дуглас Камер, Дэвид Л. Стивенс

Настоятельно рекомендую сначала осознать прочитаное ( (ага! возникает много вопросов), скачать пару-тройку уже созданных OpenSource продуктов и просмотреть их исходники.

А уже после этого с чётким пониманием ЧТО НУЖНО делать взятся за текстовый редактор, компилятор и линкер.

Это нормальный путь для обучения.

Сейчас же я наблюдаю, что вы движетесь методом проб и ошибок, после каждой нещадно осыпая окружающих вопросами.
Можно и далее пытаться вам на них отвечать, но это не будет способствовать увеличении полости вашей головной кости.

Если же вы хотите создать программный продукт проще обратиться к профессионалам.
 
Цитата
less пишет:
Рекомендую книгу "Сети TCP/IP том 3. Разработка приложений типа клиент/сервер для Linux/POSIX "
Дуглас Камер, Дэвид Л. Стивенс

Ценное замечание. Кстати книга еще и ценными, а главное корректными, примерами разбавлена.

кстати внутреннее пространство "аэродинамической трубы"   практически не меняются с 15-16 летия особи  
 
А в сети эта книга есть? гугль молчал...
Страницы: 1 2 След.
Читают тему