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

📄 tcp.scm

📁 Scheme跨平台编译器
💻 SCM
📖 第 1 页 / 共 2 页
字号:
(define tcp-connect-timeout)(define tcp-accept-timeout)(let ()  (define ((check loc) x)    (when x (##sys#check-exact x loc))    x)  (define minute (* 60 1000))  (set! tcp-read-timeout (make-parameter minute (check 'tcp-read-timeout)))  (set! tcp-write-timeout (make-parameter minute (check 'tcp-write-timeout)))   (set! tcp-connect-timeout (make-parameter #f (check 'tcp-connect-timeout)))   (set! tcp-accept-timeout (make-parameter #f (check 'tcp-accept-timeout))) )(define ##net#io-ports  (let ((make-input-port make-input-port)	(make-output-port make-output-port) 	(tbs tcp-buffer-size)	(make-string make-string) )    (lambda (fd)      (unless (##net#make-nonblocking fd)	(##sys#update-errno)	(##sys#signal-hook #:network-error (##sys#string-append "can not create TCP ports - " strerror)) )      (let* ((buf (make-string +input-buffer-size+))	     (data (vector fd #f #f))	     (buflen 0)	     (bufindex 0)	     (iclosed #f) 	     (oclosed #f)	     (outbufsize (tbs))	     (outbuf (and outbufsize (fx> outbufsize 0) ""))	     (tmr (tcp-read-timeout))	     (tmw (tcp-write-timeout))	     (read-input	      (lambda ()		(let loop ()		  (let ((n (##net#recv fd buf +input-buffer-size+ 0)))		    (cond ((eq? -1 n)			   (cond ((eq? errno _ewouldblock) 				  (when tmr				    (##sys#thread-block-for-timeout! 				     ##sys#current-thread				     (fx+ (##sys#fudge 16) tmr) ) )				  (##sys#thread-block-for-i/o! ##sys#current-thread fd #t)				  (yield)				  (when (##sys#slot ##sys#current-thread 13)				    (##sys#signal-hook				     #:network-error				     "read operation timed out" fd) )				  (loop) )				 (else				  (##sys#update-errno)				  (##sys#signal-hook 				   #:network-error				   (##sys#string-append "can not read from socket - " strerror) 				   fd) ) ) )			  (else			   (set! buflen n)			   (set! bufindex 0) ) ) ) ) ) )	     (in	      (make-input-port	       (lambda ()		 (when (fx>= bufindex buflen)		   (read-input))		 (if (fx>= bufindex buflen)		     #!eof		     (let ((c (##core#inline "C_subchar" buf bufindex)))		       (set! bufindex (fx+ bufindex 1))		       c) ) )	       (lambda ()		 (or (fx< bufindex buflen)		     (let ((f (##net#select fd)))		       (when (eq? f -1)			 (##sys#update-errno)			 (##sys#signal-hook			  #:network-error			  (##sys#string-append "can not check socket for input - " strerror) 			  fd) )		       (eq? f 1) ) ) )	       (lambda ()		 (unless iclosed		   (set! iclosed #t)		   (unless (##sys#slot data 1) (##net#shutdown fd _sd_receive))		   (when (and oclosed (eq? -1 (##net#close fd)))		     (##sys#update-errno)		     (##sys#signal-hook		      #:network-error		      (##sys#string-append "can not close socket input port - " strerror)		      fd) ) ) )	       #f	       (lambda (p n dest start)	; read-string!		 (let loop ((n n) (m 0) (start start))		   (cond ((eq? n 0) m)			 ((fx< bufindex buflen)			  (let* ((rest (fx- buflen bufindex))				 (n2 (if (fx< n rest) n rest)))			    (##core#inline "C_substring_copy" buf dest bufindex (fx+ bufindex n2) start)			    (set! bufindex (fx+ bufindex n2))			    (loop (fx- n n2) (fx+ m n2) (fx+ start n2)) ) )			 (else			  (read-input)			  (if (eq? buflen 0) 			      m			      (loop n m start) ) ) ) ) )	       (lambda (p limit)	; read-line		 (let loop ((str #f))		   (cond ((fx< bufindex buflen)			  (##sys#scan-buffer-line			   buf 			   buflen			   bufindex			   (lambda (pos2 next)			     (let ((dest (##sys#make-string (fx- pos2 bufindex))))			       (##core#inline "C_substring_copy" buf dest bufindex pos2 0)			       (set! bufindex next)			       (cond ((eq? pos2 next) ; no line-terminator encountered				      (read-input)				      (if (fx>= bufindex buflen)					  (or str "")					  (loop (if str (##sys#string-append str dest) dest)) ) )				     (else 				      (##sys#setislot p 4 (fx+ (##sys#slot p 4) 1))				      (if str (##sys#string-append str dest) dest)) ) ) ) ) )			 (else			  (read-input)			  (if (fx< bufindex buflen)			      (loop str)			      #!eof) ) ) ) ) ) )	     (output	      (lambda (s)		(let loop ((len (##sys#size s))			   (offset 0))		  (let* ((count (fxmin +output-chunk-size+ len))			 (n (##net#send fd s offset count 0)) )		    (cond ((eq? -1 n)			   (cond ((eq? errno _ewouldblock)				  (when tmw				    (##sys#thread-block-for-timeout! 				     ##sys#current-thread				     (fx+ (##sys#fudge 16) tmw) ) )				  (##sys#thread-block-for-i/o! ##sys#current-thread fd #f)				  (yield) 				  (when (##sys#slot ##sys#current-thread 13)				    (##sys#signal-hook				     #:network-error				     "write operation timed out" fd) )				  (loop len offset) )				 (else				  (##sys#update-errno)				  (##sys#signal-hook 				   #:network-error				   (##sys#string-append "can not write to socket - " strerror) 				   fd) ) ) )			  ((fx< n len)			   (loop (fx- len n) (fx+ offset n)) ) ) ) ) ) )	     (out	      (make-output-port	       (if outbuf		   (lambda (s)		     (set! outbuf (##sys#string-append outbuf s))		     (when (fx>= (##sys#size outbuf) outbufsize)		       (output outbuf)		       (set! outbuf "") ) )		   (lambda (s) 		     (when (fx> (##sys#size s) 0)		       (output s)) ) )	       (lambda ()		 (unless oclosed		   (set! oclosed #t)		   (when (and outbuf (fx> (##sys#size outbuf) 0))		     (output outbuf)		     (set! outbuf "") )		   (unless (##sys#slot data 2) (##net#shutdown fd _sd_send))		   (when (and iclosed (eq? -1 (##net#close fd)))		     (##sys#update-errno)		     (##sys#signal-hook		      #:network-error (##sys#string-append "can not close socket output port - " strerror) fd) ) ) )	       (and outbuf		    (lambda ()		      (when (fx> (##sys#size outbuf) 0)			(output outbuf)			(set! outbuf "") ) ) ) ) ) )	(##sys#setslot in 3 "(tcp)")	(##sys#setslot out 3 "(tcp)")	(##sys#setslot in 7 'socket)	(##sys#setslot out 7 'socket)	(##sys#setslot in 9 data)	(##sys#setslot out 9 data)	(values in out) ) ) ) )(define (tcp-accept tcpl)  (##sys#check-structure tcpl 'tcp-listener)  (let ((fd (##sys#slot tcpl 1))	(tma (tcp-accept-timeout)))    (let loop ()      (if (eq? 1 (##net#select fd))	  (let ((fd (##net#accept fd #f #f)))	    (when (eq? -1 fd)	      (##sys#update-errno)	      (##sys#signal-hook 	       #:network-error 'tcp-accept (##sys#string-append "could not accept from listener - " strerror) 	       tcpl) )	    (##net#io-ports fd) )	  (begin	    (when tma	      (##sys#thread-block-for-timeout! 	       ##sys#current-thread	       (fx+ (##sys#fudge 16) tma) ) )	    (##sys#thread-block-for-i/o! ##sys#current-thread fd #t)	    (yield)	    (when (##sys#slot ##sys#current-thread 13)	      (##sys#signal-hook	       #:network-error	       'tcp-accept	       "accept operation timed out" fd) )	    (loop) ) ) ) ) )(define (tcp-accept-ready? tcpl)  (##sys#check-structure tcpl 'tcp-listener 'tcp-accept-ready?)  (let ((f (##net#select (##sys#slot tcpl 1))))    (when (eq? -1 f)      (##sys#update-errno)      (##sys#signal-hook        #:network-error 'tcp-accept-ready? (##sys#string-append "can not check socket for input - " strerror)        tcpl) )    (eq? 1 f) ) )(define get-socket-error  (foreign-lambda* int ((int socket))    "int err, optlen;"    "optlen = sizeof(err);"    "if (typecorrect_getsockopt(socket, SOL_SOCKET, SO_ERROR, &err, (socklen_t *)&optlen) == -1)"    "return(-1);"    "return(err);"))(define general-strerror (foreign-lambda c-string "strerror" int))(define (tcp-connect host . more)  (let ((port (:optional more #f))	(tmc (tcp-connect-timeout)))    (##sys#check-string host)    (unless port      (set!-values (host port) (##net#parse-host host "tcp"))      (unless port (##sys#signal-hook #:network-error 'tcp-connect "no port specified" host)) )    (##sys#check-exact port)    (let ((addr (make-string _sockaddr_in_size))	  (s (##net#socket _af_inet _sock_stream 0)) )      (define (fail)	(##net#close s)	(##sys#update-errno)	(##sys#signal-hook 	 #:network-error 'tcp-connect (##sys#string-append "can not connect to socket - " strerror) 	 host port) )      (when (eq? -1 s)	(##sys#update-errno)	(##sys#signal-hook #:network-error 'tcp-connect (##sys#string-append "can not create socket - " strerror) host port) )      (unless (##net#gethostaddr addr host port)	(##sys#signal-hook #:network-error 'tcp-connect "can not find host address" host) )      (unless (##net#make-nonblocking s)	(##sys#update-errno)	(##sys#signal-hook #:network-error 'tcp-connect (##sys#string-append "fcntl() failed - " strerror)) )      (when (eq? -1 (##net#connect s addr _sockaddr_in_size))	(if (eq? errno _einprogress)	    (let loop ()	      (let ((f (##net#select-write s)))		(when (eq? f -1) (fail))		(unless (eq? f 1)		  (when tmc		    (##sys#thread-block-for-timeout!		     ##sys#current-thread		     (fx+ (##sys#fudge 16) tmc) ) )		  (##sys#thread-block-for-i/o! ##sys#current-thread s #:all)		  (yield)		  (when (##sys#slot ##sys#current-thread 13)		    (##sys#signal-hook		     #:network-error		     'tcp-connect		     "connect operation timed out" s) )		  (loop) ) ) )	    (fail) ) )      (let ((err (get-socket-error s)))	(cond ((= err -1) 	       (##sys#signal-hook #:network-error 'tcp-connect (##sys#string-append "getsockopt() failed - " strerror)))	      ((> err 0) 	       (##sys#signal-hook #:network-error 'tcp-connect (##sys#string-append "can not create socket - " (general-strerror err))))))      (##net#io-ports s) ) ) )(define (##sys#tcp-port->fileno p)  (##sys#slot (##sys#port-data p) 0) )(define (tcp-addresses p)  (let ((fd (##sys#tcp-port->fileno p)))    (values      (or (##net#getsockname fd)	 (##sys#signal-hook #:network-error 'tcp-addresses (##sys#string-append "can not compute local address - " strerror) p) )     (or (##net#getpeername fd)	 (##sys#signal-hook #:network-error 'tcp-addresses (##sys#string-append "can not compute remote address - " strerror) p) ) ) ) )(define (tcp-port-numbers p) (let ((fd (##sys#tcp-port->fileno p)))   (values    (or (##net#getsockport fd)        (##sys#signal-hook #:network-error 'tcp-port-numbers (##sys#string-append "can not compute local port - " strerror) p) )    (or (##net#getpeerport fd)        (##sys#signal-hook #:network-error 'tcp-port-numbers (##sys#string-append "can not compute remote port - " strerror) p) ) ) ) )(define (tcp-listener-port tcpl)  (##sys#check-structure tcpl 'tcp-listener 'tcp-listener-port)  (let* ((fd (##sys#slot tcpl 1))	 (port (##net#getsockport fd)) )    (when (eq? -1 port)      (##sys#signal-hook       #:network-error 'tcp-listener-port (##sys#string-append "can not obtain listener port - " strerror)        tcpl fd) )    port) )(define (tcp-abandon-port p)  (##sys#check-port p 'tcp-abandon-port)  (##sys#setislot   (##sys#port-data p)   (if (##sys#slot p 1) 2 1)   #t) )(define (tcp-listener-fileno l)  (##sys#check-structure l 'tcp-listener 'tcp-listener-fileno)  (##sys#slot l 1) )

⌨️ 快捷键说明

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