The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

Proxy Wrapper: Оцените программку (proxy example socket)


<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>
Ключевые слова: proxy, example, socket,  (найти похожие документы)
_ RU.UNIX (2:5077/15.22) _____________________________________________ RU.UNIX _ From : Alexei Yesipenko 2:5061/109.61 18 Jun 99 09:34:54 Subj : Proxy Wrapper: Оцените программку ________________________________________________________________________________ Hello All. Хочу услышать ваше мнение по поводу первой моей программки под Unix. Ситуация такая: имеется proxy c выходом в инет; имеется машинка под Linux box, которой позволено ходить на proxy; Цель программы: программа должна позволять хождение с моей машины (Win95) в инет, с использованием IE или NN, при условии если я имею логин на машину с Linuxом. Перенаправление пакетов через ядро реализовать нельзя, т.к. ядро старое - 2.0.30. Вот собственно, какую программку я для этого придумал. === Cut === #define PORT_IN 8983 #define PORT_OUT 8080 #include <string.h> #include <sys/types.h> #include <sys/time.h> #include <sys/wait.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdio.h> #include <fcntl.h> #include <netdb.h> #include <unistd.h> #include <errno.h> #include <netinet/in.h> #include <stdlib.h> #include <unistd.h> #include <pbmplus.h> #include <signal.h> int connect_proxy(char *name) { struct hostent *host; struct sockaddr_in s_addr; int sock; host = gethostbyname(name); if (!host) return -1; if ( (sock = socket(AF_INET,SOCK_STREAM,0)) == -1 ) return -1; s_addr.sin_family = AF_INET; s_addr.sin_port = htons( PORT_OUT ); memcpy((char*)&s_addr.sin_addr,host->h_addr_list[0],host->h_length); if ( connect(sock,(struct sockaddr*)&s_addr,sizeof(s_addr)) == -1 ) { close(sock); return -1; } return sock; } int setup_server() { int sock; struct sockaddr_in s_addr; if ( (sock=socket(AF_INET,SOCK_STREAM,0)) == -1 ) { perror("call socket() error"); return -1; } memset(&s_addr,0,sizeof(s_addr)); s_addr.sin_family = AF_INET; s_addr.sin_addr.s_addr = INADDR_ANY; s_addr.sin_port = htons(PORT_IN); if ( bind(sock,(struct sockaddr *)&s_addr,sizeof(s_addr)) == -1 ) { perror("call bind() error"); Err: close(sock); return -1; } if ( listen(sock,5) == -1 ) { perror("call listen() error"); goto Err; } puts("Server ready..."); return sock; } int run_server(int sock,char* proxy) { struct timeval tv; int p_sock = connect_proxy(proxy); int fl_quit = 0,r; char *buff_pr = malloc(8*1024); char *buff_cl = malloc(8*1024); int blen_pr, blen_cl; if ( (p_sock != -1) && buff_pr && buff_cl ) { fcntl(sock, F_SETFL, O_NONBLOCK); fcntl(p_sock, F_SETFL, O_NONBLOCK); while (!fl_quit) { r = 0; blen_cl = recv(sock,buff_cl,8*1024,0); if ( blen_cl == 0 ) fl_quit = 1; if ( blen_cl == -1 && errno == EWOULDBLOCK ) blen_cl = 0, r++; blen_pr = recv(p_sock,buff_pr,8*1024,0); if ( blen_pr == 0 ) fl_quit = 1; if ( blen_pr == -1 && errno == EWOULDBLOCK ) blen_pr = 0, r++; if ( r == 2 ) { tv.tv_sec = 0; tv.tv_usec = 100; select(0,NULL,NULL,NULL,&tv); } else { if (blen_cl) if ( blen_cl == -1 || send( p_sock,buff_cl,blen_cl,0) == -1) fl_quit = 1; if (blen_pr) if ( blen_pr == -1 || send( sock,buff_pr,blen_pr,0) == -1) fl_quit = 1; } } close(p_sock); } if (buff_pr) free(buff_pr); if (buff_cl) free(buff_cl); close(sock); } int main(int argc, char **argv) { int sock,c_sock,s_addr_len,pid; struct sockaddr_in s_addr; if (argc == 2) { if ( (sock=setup_server()) != -1 ) { for(;;) { memset(&s_addr,0,s_addr_len = sizeof(s_addr)); if ( (c_sock = accept(sock, (struct sockaddr*)&s_addr, &s_addr_len)) == -1) { perror("call accept() error"); return 1; } fprintf(stderr,"Connect from %s\n", inet_ntoa(s_addr.sin_addr)); while ( (waitpid(-1,&pid,WNOHANG) != -1) && WIFEXITED(pid) ); if ( (pid = fork()) == -1 ) { perror("call fork() error"); return 1; } if ( !pid ) { close(sock); run_server(c_sock,argv[1]); exit(0); } close(c_sock); } } } else puts("Usage: proxysrv <proxy_host_name>"); return 0; } === Cut === Правильно ли я избавляюсь от зомби? При работе с IE иногда вылетает странная ошибка: call accept() error: Connection reset by peer Как правильно и проще закрывать порты при Ctrl-C? WBR, Alexei. --- * Origin: -= YesAl station =- (2:5061/109.61) _ RU.UNIX (2:5077/15.22) _____________________________________________ RU.UNIX _ From : Oleg Derevenetz 2:5025/3.4 18 Jun 99 13:13:28 Subj : Proxy Wrapper: Оцените программку ________________________________________________________________________________ Hello Alexei! At 18 Jun 99 09:34:54, Alexei Yesipenko wrote to All: AY> Правильно ли я избавляюсь от зомби? Вообще-то говоря, совсем правильно было бы повесить следующий обработчик на SIGCHLD : void KillZombies (int) { int Status; waitpid (-1, &Status, WHOHANG); signal (SIGCHLD, KillZombies); } AY> При работе с IE иногда вылетает странная ошибка: AY> call accept() error: Connection reset by peer С чьей стороны ? IE или твоей программы ? AY> Как правильно и проще закрывать порты при Ctrl-C? Повесить обработчик на SIGINT. > [KILL THE YANKEE TEAM] [Team 5 колонну давить] --- QDed beta v1.3 under FreeBSD 3.1-STABLE * Origin: Взялся за гуж - полезай в кузов... (2:5025/3.4) _ RU.UNIX (2:5077/15.22) _____________________________________________ RU.UNIX _ From : Michael Kondrashin 2:5020/128 24 Jun 99 13:00:02 Subj : Re: Proxy Wrapper: Оцените программку ________________________________________________________________________________ From: [email protected] (Michael Kondrashin) > > Плохо. Hекотоpые системы (не буду упоминать) стpадают тем, что могут выдать > > положительный pезультат по select() и затем заблокиpовать recv(). Так что > > безусловно лучше даже пpи select'е пользовать NONBLOCK. > Hадо попробывать сформулировать здесь "идеальный" цикл для этой задачи. Всем кто может чего-либо посоветовать: подправте и опубликуйте. Мой вариант: for(;;) { FD_ZERO(&fdset); FD_SET(s1, &fdset); FD_SET(s2, &fdset); rc = select(max, &fdset, 0, 0, 0); if( rc == -1 ) { if( errno == EINTR ) continue; printf("Error calling select: %s\n", strerror(errno)); return 1; } if( FD_ISSET(s, &fdset) ) { int err = copy(s1, s2); switch( err ) { case 1: puts("1 closed connection") return 0; case 0: if( rc == 1) continue; default: return err; } } if( FD_ISSET(s2, &fdset) ) { int err = copy(s2, s1); switch( err ) { case 1: puts("2 closed connection") return 0; case 0: continue; default: return err; } } puts("Select cycle internal error"); return 1; } -------------------- int copy(int from, int to) { int i_sz, o_sz; char buf[BUF_SIZE]; i_sz = recv(from, buf, BUF_SIZE, 0); if( i_sz == 0 ) return 1; // Connection closed if( i_sz == -1 ) { if( errno == ECONNRESET ) return 1; // Is it right? printf("Error calling recv: %s\n", strerror(errno)); return 2; } o_sz = send(to, buf, i_sz, 0); if( o_sz == -1 ) { printf("Error calling send: %s\n", strerror(errno)); return 3; } if( i_sz != o_sz ) { // How this can heaped? printf("Read %d bytes, wrote %d", i_sz, o_sz); return 4; } return 0; } Здесь не хватает -учета продлемы поднятой в цитате -send то же может быть заблокирован. -Что еще? --- ifmail v.2.10dev * Origin: Applied Logistics (2:5020/128@fidonet) _ RU.UNIX (2:5077/15.22) _____________________________________________ RU.UNIX _ From : Valentin Nechayev 2:5020/400 25 Jun 99 12:44:14 Subj : Re: Proxy Wrapper: Оцените программку ________________________________________________________________________________ From: "Valentin Nechayev" <[email protected]> Reply-To: [email protected] Hello Michael Kondrashin! At 24-Jun-99 12:00, Michael Kondrashin wrote: > rc = select(max, &fdset, 0, 0, 0); > if( rc == -1 ) { > if( errno == EINTR ) continue; > printf("Error calling select: %s\n", strerror(errno)); > return 1; А вот pугаться тут незачем - ошибка в select'е некpитична > } > > if( FD_ISSET(s, &fdset) ) { Кто такой s? > int err = copy(s1, s2); > switch( err ) { [skip] Ох вы боги мои... #define BS 1000 char lr_buf[BS], rl_buf[BS]; int leof, reof, lr_pos, rl_pos, lr_cnt, rl_cnt; leof = reof = lr_pos = rl_pos = lr_cnt = rl_cnt = 0; for(;;) { if( leof && reof ) return "total eof"; if( fdLeft < FD_SETSIZE && fdRight < FD_SETSIZE ) { fd_set fdr, fdw; struct timeval tv; int maxfd = fdLeft > fdRight ? fdLeft : fdRight; int got; /* Ожидание */ FD_ZERO( &fdr ); FD_ZERO( &fdw ); if( lr_cnt < BS ) FD_SET( fdLeft, &fdr ); if( lr_cnt > 0 ) FD_SET( fdRight, &fdw ); if( rl_cnt < BS ) FD_SET( fdRight, &fdr ); if( rl_cnt > 0 ) FD_SET( fdLeft, &fdw ); tv.tv_sec = 4; tv.tv_usec = 0; select( maxfd+1, &fdr, &fdw, NULL, &tv ); /* Hоpмализация буфеpов */ if( lr_pos > 0 ) { memmove( lr_buf, lr_buf + lr_pos, lr_cnt ); lr_pos = 0; } if( rl_pos > 0 ) { memmove( rl_buf, rl_buf + rl_pos, rl_cnt ); rl_pos = 0; } /* Чтение/запись */ if( FD_ISSET( fdLeft, &fdr ) ) { rc = read( fdLeft, lr_buf + lr_pos + lr_cnt, BS - lr_buf - lr_cnt ); if( rc == -1 && errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN ) return "error"; if( rc == 0 ) l_eof = 1; if( rc > 0 ) lr_cnt += rc; } if( FD_ISSET( fdRight, &fdr ) ) { rc = read( fdRight, rl_buf + rl_pos + rl_cnt, BS - rl_buf - rl_cnt ); if( rc == -1 && errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN ) return "error"; if( rc == 0 ) r_eof = 1; if( rc > 0 ) rl_cnt += rc; } if( FD_ISSET( fdLeft, &fdw ) ) { rc = write( fdLeft, rl_buf + rl_pos, rl_cnt ); if( rc == -1 && errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN ) return "error"; if( rc > 0 ) rl_pos += rc, rl_cnt -= rc; } if( FD_ISSET( fdRight, &fdw ) ) { rc = write( fdRight, lr_buf + lr_pos, lr_cnt ); if( rc == -1 && errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN ) return "error"; if( rc > 0 ) lr_pos += rc, lr_cnt -= rc; } Все. Отлаживайте и пускайте. -- NN --- ifmail v.2.14dev3 * Origin: unknown (2:5020/400) _ RU.UNIX (2:5077/15.22) _____________________________________________ RU.UNIX _ From : Alexei Yesipenko 2:5061/109.61 28 Jun 99 09:48:44 Subj : Proxy Wrapper: Оцените программку ________________________________________________________________________________ Hello Valentin. Пят Июн 25 1999 12:44, Valentin Nechayev wrote to Michael Kondrashin: VN> /* Hоpмализация буфеpов */ VN> if( lr_pos > 0 ) { VN> memmove( lr_buf, lr_buf + lr_pos, lr_cnt ); VN> lr_pos = 0; VN> } VN> } Что так сложно-то? Попробую предложить второй ошибочный вариант, но попроще... === Cut === #define CP_BUFF_SZ 2048 int cp_sock(int to, int from) { struct timeval tv; char buf[CP_BUFF_SZ]; fd_set fdr,fdw; int r,sz; FD_ZERO(&fdr); FD_SET(to,&fdr); FD_SET(from,&fdr); tv.tv_sec = 10; tv.tv_usec = 0; if ( r = select( (from>to?from:to)+1, &fdr, NULL, NULL, &tv) ) { if (r<0) return 1; if ( FD_ISSET(from, &fdr) ) { sz = recv(from,buf,CP_BUFF_SZ,0); if (sz<=0) return 2; FD_ZERO(&fdw); FD_SET(to,&fdw); tv.tv_sec = 10; tv.tv_usec = 0; if ( select(to+1, NULL, &fdw, NULL, &tv) <= 0 || send(to,buf,sz,0) <= 0 ) return 3; } } return 0; } // А вот цикл: while( !(cp_sock(p_sock,sock) ||cp_sock(sock,p_sock)) ); === Cut === Вообще то, это не критично. Меня другая проблема интересует. Как корректно выйти из этой программки? Shutdown с последующим close не работает. Если был хоть один коннект со стороны клиента, то последующий запуск сервера (после Ctrl-C) вылетает c ошибкой bind(), что данный сокет уже используется. Хотя это тоже не критично, секунд через 30 сокет сам освобождается, но хотелось бы знать как это в принципе работает. И еще. А есть ли книга или faq типа "Программирование под UNIX для программистов под DOS"? В Unixe прекрасный инструментарий, например strace. WBR, Alexei. --- * Origin: -= YesAl station =- (FidoNet 2:5061/109.61)

<< Предыдущая ИНДЕКС Поиск в статьях src Установить закладку Перейти на закладку Следующая >>

Обсуждение [ RSS ]
  • 1, Аноним (1), 16:15, 16/12/2002 [ответить]  
  • +/
    try to set SO_REUSEADDR socket option
     
  • 2, Senka (?), 22:34, 23/03/2003 [ответить]  
  • +/
    Условие такое же, но стоит NT у нее закрыты все порты (кроме системных). Нужно что бы эта прога коннектилась из под Linux к тачке, открывала порт, а затем его слушала. Если начинают поступать запросы , она начинает передавать данные (запросы могут быть как от браузера, так и от ssh клиента).
     

    игнорирование участников | лог модерирования

     Добавить комментарий
    Имя:
    E-Mail:
    Заголовок:
    Текст:




    Партнёры:
    PostgresPro
    Inferno Solutions
    Hosting by Hoster.ru
    Хостинг:

    Закладки на сайте
    Проследить за страницей
    Created 1996-2024 by Maxim Chirkov
    Добавить, Поддержать, Вебмастеру