@@ -226,6 +226,76 @@ Go语言中通过net包中的`DialTCP`函数来建立一个TCP连接,并返回
226226
227227通过把业务处理分离到函数` handleClient ` ,我们就可以进一步地实现多并发执行了。看上去是不是很帅,增加` go ` 关键词就实现了服务端的多并发,从这个小例子也可以看出goroutine的强大之处。
228228
229+ 有的朋友可能要问:这个服务端没有处理客户端实际请求的内容。如果我们需要通过从客户端发送不同的请求来获取不同的时间格式,而且需要一个长连接,该怎么做呢?请看:
230+ 
231+ 	package main 
232+ 
233+ 	import ( 
234+ 		"fmt" 
235+ 		"net" 
236+ 		"os" 
237+ 		"time" 
238+ 		"strconv" 
239+ 	) 
240+ 
241+ 	func main() { 
242+ 		service := ":1200" 
243+ 		tcpAddr, err := net.ResolveTCPAddr("tcp4", service) 
244+ 		checkError(err) 
245+ 		listener, err := net.ListenTCP("tcp", tcpAddr) 
246+ 		checkError(err) 
247+ 		for { 
248+ 			conn, err := listener.Accept() 
249+ 			if err != nil { 
250+ 				continue 
251+ 			} 
252+ 			go handleClient(conn) 
253+ 		} 
254+ 	} 
255+ 
256+ 	func handleClient(conn net.Conn) { 
257+ 		conn.SetReadDeadline(time.Now().Add(2 * time.Minute)) // set 2 minutes timeout 
258+ 		request := make([]byte, 128) // set maxium request length to 128KB to prevent flood attack 
259+ 		 
260+ 		for { 
261+ 			read_len, err := conn.Read(request) 
262+ 
263+ 			if err != nil { 
264+ 				if err != io.EOF { // ignore EOF since client might send nothing for the moment 
265+ 					fmt.Println(err) 
266+ 					break 
267+ 				} 
268+ 
269+ 				neterr, ok := err.(net.Error) 
270+ 				if ok && neterr.Timeout() { 
271+ 					fmt.Println(neterr) 
272+ 					break 
273+ 				} 
274+ 			} 
275+ 
276+     		if read_len == 0 { 
277+       			continue 
278+     		} else if string(request) == "timestamp" { 
279+     			daytime := strconv.FormatInt(time.Now().Unix(), 10) 
280+     			conn.Write([]byte(daytime)) 
281+     		} else { 
282+     			daytime := time.Now().String() 
283+     			conn.Write([]byte(daytime))  
284+     		} 
285+ 
286+     		request = make([]byte, 128) // clear last read content 
287+ 		} 
288+ 	} 
289+ 
290+ 	func checkError(err error) { 
291+ 		if err != nil { 
292+ 			fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error()) 
293+ 			os.Exit(1) 
294+ 		} 
295+ 	} 
296+ 
297+ 在上面这个例子中,我们使用` conn.Read() ` 不断读取客户端发来的请求。由于我们需要保持与客户端的长连接,所以不能在读取完一次请求后就关闭连接。由于` conn.SetReadDeadline() ` 设置了超时,当一定时间内客户端无请求发送,` conn ` 便会自动关闭,下面的for循环即会因为连接已关闭而跳出。需要注意的是,` request ` 在创建时需要指定一个最大长度以防止flood attack;每次读取到请求处理完毕后,需要清理request,因为` conn.Read() ` 会将新读取到的内容append到原内容之后。
298+ 
229299### 控制TCP连接  
230300TCP有很多连接控制函数,我们平常用到比较多的有如下几个函数:
231301
0 commit comments