⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcp.scm

📁 Scheme跨平台编译器
💻 SCM
📖 第 1 页 / 共 2 页
字号:
;;;; tcp.scm - Networking stuff;; Copyright (c) 2000-2007, Felix L. Winkelmann; Copyright (c) 2008, The Chicken Team; All rights reserved.;; Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following; conditions are met:;;   Redistributions of source code must retain the above copyright notice, this list of conditions and the following;     disclaimer. ;   Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following;     disclaimer in the documentation and/or other materials provided with the distribution. ;   Neither the name of the author nor the names of its contributors may be used to endorse or promote;     products derived from this software without specific prior written permission. ;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY; AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE; POSSIBILITY OF SUCH DAMAGE.(declare  (unit tcp)  (uses data-structures ports extras scheduler)  (usual-integrations)  (fixnum-arithmetic)  (no-bound-checks)  (export tcp-close tcp-listen tcp-connect tcp-accept tcp-accept-ready? ##sys#tcp-port->fileno tcp-listener? tcp-addresses	  tcp-abandon-port tcp-listener-port tcp-listener-fileno tcp-port-numbers tcp-buffer-size	  tcp-read-timeout tcp-write-timeout tcp-accept-timeout tcp-connect-timeout)  (no-procedure-checks-for-usual-bindings)  (bound-to-procedure   ##net#socket ##net#bind ##net#connect ##net#listen ##net#accept make-parameter ##sys#string-append ##sys#tcp-port->fileno   ##sys#check-port ##sys#port-data ##sys#thread-block-for-i/o! make-string make-input-port make-output-port ##sys#substring   substring ##sys#make-c-string ##sys#schedule   ##net#close ##net#recv ##net#send ##net#select ##net#select-write ##net#gethostaddr ##net#io-ports ##sys#update-errno   ##sys#error ##sys#signal-hook ##net#getservbyname ##net#parse-host ##net#fresh-addr   ##net#bind-socket ##net#shutdown)  (foreign-declare #<<EOF#include <errno.h>#ifdef _WIN32# if _MSC_VER > 1300# include <winsock2.h># include <ws2tcpip.h># else# include <winsock.h># endif/* Beware: winsock2.h must come BEFORE windows.h */# define socklen_t       intstatic WSADATA wsa;# define fcntl(a, b, c)  0# define EWOULDBLOCK     0# define EINPROGRESS     0# define typecorrect_getsockopt(socket, level, optname, optval, optlen)	\    getsockopt(socket, level, optname, (char *)optval, optlen)#else# include <fcntl.h># include <sys/types.h># include <sys/socket.h># include <sys/time.h># include <netinet/in.h># include <unistd.h># include <netdb.h># include <signal.h># define closesocket     close# define INVALID_SOCKET  -1# define typecorrect_getsockopt getsockopt#endif#ifndef SD_RECEIVE# define SD_RECEIVE      0# define SD_SEND         1#endif#ifdef ECOS#include <sys/sockio.h>#endifstatic char addr_buffer[ 20 ];EOF) )(register-feature! 'tcp)(cond-expand (unsafe  (eval-when (compile)    (define-macro (##sys#check-structure x y . _) '(##core#undefined))    (define-macro (##sys#check-range x y z) '(##core#undefined))    (define-macro (##sys#check-pair x) '(##core#undefined))    (define-macro (##sys#check-list x) '(##core#undefined))    (define-macro (##sys#check-symbol x) '(##core#undefined))    (define-macro (##sys#check-string x) '(##core#undefined))    (define-macro (##sys#check-char x) '(##core#undefined))    (define-macro (##sys#check-exact x . _) '(##core#undefined))    (define-macro (##sys#check-port x . _) '(##core#undefined))    (define-macro (##sys#check-number x) '(##core#undefined)))) (else  (declare (emit-exports "tcp.exports"))) )(define-foreign-variable errno int "errno")(define-foreign-variable strerror c-string "strerror(errno)")(define-foreign-type sockaddr* (pointer "struct sockaddr"))(define-foreign-type sockaddr_in* (pointer "struct sockaddr_in"))(define-foreign-variable _af_inet int "AF_INET")(define-foreign-variable _sock_stream int "SOCK_STREAM")(define-foreign-variable _sock_dgram int "SOCK_DGRAM")(define-foreign-variable _sockaddr_size int "sizeof(struct sockaddr)")(define-foreign-variable _sockaddr_in_size int "sizeof(struct sockaddr_in)")(define-foreign-variable _sd_receive int "SD_RECEIVE")(define-foreign-variable _sd_send int "SD_SEND")(define-foreign-variable _ipproto_tcp int "IPPROTO_TCP")(define-foreign-variable _invalid_socket int "INVALID_SOCKET")(define-foreign-variable _ewouldblock int "EWOULDBLOCK")(define-foreign-variable _einprogress int "EINPROGRESS")(define ##net#socket (foreign-lambda int "socket" int int int))(define ##net#bind (foreign-lambda int "bind" int scheme-pointer int))(define ##net#listen (foreign-lambda int "listen" int int))(define ##net#accept (foreign-lambda int "accept" int c-pointer c-pointer))(define ##net#close (foreign-lambda int "closesocket" int))(define ##net#recv (foreign-lambda int "recv" int scheme-pointer int int))(define ##net#shutdown (foreign-lambda int "shutdown" int int))(define ##net#connect (foreign-lambda int "connect" int scheme-pointer int))(define ##net#send  (foreign-lambda* int ((int s) (scheme-pointer msg) (int offset) (int len) (int flags))		   "return(send(s, (char *)msg+offset, len, flags));"))(define ##net#make-nonblocking  (foreign-lambda* bool ((int fd))    "int val = fcntl(fd, F_GETFL, 0);"    "if(val == -1) return(0);"    "return(fcntl(fd, F_SETFL, val | O_NONBLOCK) != -1);") )(define ##net#getsockname   (foreign-lambda* c-string ((int s))    "struct sockaddr_in sa;"    "unsigned char *ptr;"    "int len = sizeof(struct sockaddr_in);"    "if(getsockname(s, (struct sockaddr *)&sa, (socklen_t *)&len) != 0) return(NULL);"    "ptr = (unsigned char *)&sa.sin_addr;"    "sprintf(addr_buffer, \"%d.%d.%d.%d\", ptr[ 0 ], ptr[ 1 ], ptr[ 2 ], ptr[ 3 ]);"    "return(addr_buffer);") )(define ##net#getsockport  (foreign-lambda* int ((int s))    "struct sockaddr_in sa;"    "int len = sizeof(struct sockaddr_in);"    "if(getsockname(s, (struct sockaddr *)&sa, (socklen_t *)(&len)) != 0) return(-1);"    "else return(ntohs(sa.sin_port));") )(define ##net#getpeerport (foreign-lambda* int ((int s))   "struct sockaddr_in sa;"   "int len = sizeof(struct sockaddr_in);"   "if(getpeername(s, (struct sockaddr *)&sa, (socklen_t *)(&len)) != 0) return(-1);"   "else return(ntohs(sa.sin_port));") )(define ##net#getpeername   (foreign-lambda* c-string ((int s))    "struct sockaddr_in sa;"    "unsigned char *ptr;"    "unsigned int len = sizeof(struct sockaddr_in);"    "if(getpeername(s, (struct sockaddr *)&sa, ((unsigned int *)&len)) != 0) return(NULL);"    "ptr = (unsigned char *)&sa.sin_addr;"    "sprintf(addr_buffer, \"%d.%d.%d.%d\", ptr[ 0 ], ptr[ 1 ], ptr[ 2 ], ptr[ 3 ]);"    "return(addr_buffer);") )(define ##net#startup  (foreign-lambda* bool () #<<EOF#ifdef _WIN32     return(WSAStartup(MAKEWORD(1, 1), &wsa) == 0);#else     signal(SIGPIPE, SIG_IGN);     return(1);#endifEOF) )(unless (##net#startup)  (##sys#signal-hook #:network-error "can not initialize Winsock") )(define ##net#getservbyname   (foreign-lambda* int ((c-string serv) (c-string proto))    "struct servent *se;     if((se = getservbyname(serv, proto)) == NULL) return(0);     else return(ntohs(se->s_port));") )     (define ##net#select  (foreign-lambda* int ((int fd))    "fd_set in;     struct timeval tm;     int rv;     FD_ZERO(&in);     FD_SET(fd, &in);     tm.tv_sec = tm.tv_usec = 0;     rv = select(fd + 1, &in, NULL, NULL, &tm);     if(rv > 0) { rv = FD_ISSET(fd, &in) ? 1 : 0; }     return(rv);") )(define ##net#select-write  (foreign-lambda* int ((int fd))    "fd_set out;     struct timeval tm;     int rv;     FD_ZERO(&out);     FD_SET(fd, &out);     tm.tv_sec = tm.tv_usec = 0;     rv = select(fd + 1, NULL, &out, NULL, &tm);     if(rv > 0) { rv = FD_ISSET(fd, &out) ? 1 : 0; }     return(rv);") )(define ##net#gethostaddr  (foreign-lambda* bool ((scheme-pointer saddr) (c-string host) (unsigned-short port))    "struct hostent *he = gethostbyname(host);"    "struct sockaddr_in *addr = (struct sockaddr_in *)saddr;"    "if(he == NULL) return(0);"    "memset(addr, 0, sizeof(struct sockaddr_in));"    "addr->sin_family = AF_INET;"    "addr->sin_port = htons((short)port);"    "addr->sin_addr = *((struct in_addr *)he->h_addr);"    "return(1);") )(define (yield)  (##sys#call-with-current-continuation   (lambda (return)     (let ((ct ##sys#current-thread))       (##sys#setslot ct 1 (lambda () (return (##core#undefined))))       (##sys#schedule) ) ) ) )(define ##net#parse-host  (let ((substring substring))    (lambda (host proto)      (let ((len (##sys#size host)))	(let loop ((i 0))	  (if (fx>= i len)	      (values host #f)	      (let ((c (##core#inline "C_subchar" host i)))		(if (char=? c #\:)		    		    (values		     (substring host (add1 i) len)		     (let* ((s (substring host 0 i))			    (p (##net#getservbyname s proto)) )		       (when (eq? 0 p)			 (##sys#update-errno)			 (##sys#signal-hook			  #:network-error 'tcp-connect (##sys#string-append "can not compute port from service - " strerror)			  s) )		       p) )		    (loop (fx+ i 1)) ) ) ) ) ) ) ) )(define ##net#fresh-addr  (foreign-lambda* void ((scheme-pointer saddr) (unsigned-short port))    "struct sockaddr_in *addr = (struct sockaddr_in *)saddr;"    "memset(addr, 0, sizeof(struct sockaddr_in));"    "addr->sin_family = AF_INET;"    "addr->sin_port = htons(port);"    "addr->sin_addr.s_addr = htonl(INADDR_ANY);") )(define (##net#bind-socket port style host)  (##sys#check-exact port)  (cond-expand   (unsafe)   (else    (when (or (fx< port 0) (fx>= port 65535))      (##sys#signal-hook #:domain-error 'tcp-listen "invalid port number" port) ) ) )  (let ((s (##net#socket _af_inet style 0)))    (when (eq? _invalid_socket s)      (##sys#update-errno)      (##sys#error "can not create socket") )    ;; PLT makes this an optional arg to tcp-listen. Should we as well?    (when (eq? -1 ((foreign-lambda* int ((int socket)) 		     "int yes = 1;                       return(setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&yes, sizeof(int)));") 		   s) )      (##sys#update-errno)      (##sys#signal-hook #:network-error 'tcp-listen (##sys#string-append "error while setting up socket - " strerror) s) )    (let ((addr (make-string _sockaddr_in_size)))      (if host	  (unless (##net#gethostaddr addr host port)	    (##sys#signal-hook #:network-error 'tcp-listen "getting listener host IP failed - " host port) )	  (##net#fresh-addr addr port) )      (let ((b (##net#bind s addr _sockaddr_in_size)))	(when (eq? -1 b)	  (##sys#update-errno)	  (##sys#signal-hook #:network-error 'tcp-listen (##sys#string-append "can not bind to socket - " strerror) s port) )	(values s addr) ) ) ) )(define-constant default-backlog 10)(define (tcp-listen port . more)  (let-optionals more ((w default-backlog) (host #f))    (let-values (((s addr) (##net#bind-socket port _sock_stream host)))      (##sys#check-exact w)      (let ((l (##net#listen s w)))	(when (eq? -1 l)	  (##sys#update-errno)	  (##sys#signal-hook #:network-error 'tcp-listen (##sys#string-append "can not listen on socket - " strerror) s port) )	(##sys#make-structure 'tcp-listener s) ) ) ) )(define (tcp-listener? x)   (and (##core#inline "C_blockp" x)       (##sys#structure? x 'tcp-listener) ) )(define (tcp-close tcpl)  (##sys#check-structure tcpl 'tcp-listener)  (let ((s (##sys#slot tcpl 1)))    (when (fx= -1 (##net#close s))      (##sys#update-errno)      (##sys#signal-hook #:network-error 'tcp-close (##sys#string-append "can not close TCP socket - " strerror) tcpl) ) ) )(define-constant +input-buffer-size+ 1024)(define-constant +output-chunk-size+ 8192)(define tcp-buffer-size (make-parameter #f))(define tcp-read-timeout)(define tcp-write-timeout)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -