|
|
@@ -5,6 +5,7 @@
|
|
|
服务器代码,单独的一个文件:
|
|
|
|
|
|
示例 15.1 [server.go](examples/chapter_15/server.go)
|
|
|
+
|
|
|
```go
|
|
|
package main
|
|
|
|
|
|
@@ -51,6 +52,7 @@ func doServerStuff(conn net.Conn) {
|
|
|
客户端代码写在另外一个文件client.go中:
|
|
|
|
|
|
示例 15.2 [client.go](examples/chapter_15/client.go)
|
|
|
+
|
|
|
```go
|
|
|
package main
|
|
|
|
|
|
@@ -107,6 +109,7 @@ func main() {
|
|
|
然后开启2个或者3个独立的控制台窗口,然后分别输入client回车启动客户端程序
|
|
|
|
|
|
以下是服务器的输出:
|
|
|
+
|
|
|
```
|
|
|
Starting the Server ...
|
|
|
Received data: IVO says: Hi Server, what's up ?
|
|
|
@@ -114,6 +117,7 @@ Received data: CHRIS says: Are you busy server ?
|
|
|
Received data: MARC says: Don't forget our appointment tomorrow !
|
|
|
```
|
|
|
当客户端输入 Q 并结束程序时,服务器会输出以下信息:
|
|
|
+
|
|
|
```
|
|
|
Error reading WSARecv tcp 127.0.0.1:50000: The specified network name is no longer available.
|
|
|
```
|
|
|
@@ -122,6 +126,7 @@ Error reading WSARecv tcp 127.0.0.1:50000: The specified network name is no long
|
|
|
下边这个示例先使用TCP协议连接远程80端口,然后使用UDP协议连接,最后使用TCP协议连接IPv6类型的地址:
|
|
|
|
|
|
示例 15.3 [dial.go](examples/chapter_15/dial.go)
|
|
|
+
|
|
|
```go
|
|
|
// make a connection with www.example.org:
|
|
|
package main
|
|
|
@@ -151,6 +156,7 @@ func checkConnection(conn net.Conn, err error) {
|
|
|
下边也是一个使用net包从socket中打开,写入,读取数据的例子:
|
|
|
|
|
|
示例 15.4 [socket.go](examples/chapter_15/socket.go)
|
|
|
+
|
|
|
```go
|
|
|
package main
|
|
|
|
|
|
@@ -183,7 +189,10 @@ func main() {
|
|
|
con.Close()
|
|
|
}
|
|
|
```
|
|
|
-**练习 15.1** 编写新版本的客户端和服务器([client1.go](exercises/chapter_15/client1.go) / [server1.go](exercises/chapter_15/server1.go)):
|
|
|
+**练习 15.1**
|
|
|
+
|
|
|
+编写新版本的客户端和服务器([client1.go](exercises/chapter_15/client1.go) / [server1.go](exercises/chapter_15/server1.go)):
|
|
|
+
|
|
|
* 增加一个检查错误的函数`checkError(error)`;讨论如下方案的利弊:为什么这个重构可能并没有那么理想?看看在[示例15.14](examples/chapter_15/template_validation.go)中它是如何被解决的
|
|
|
* 使客户端可以通过发送一条命令SH来关闭服务器
|
|
|
* 让服务器可以保存已经连接的客户端列表(他们的名字);当客户端发送WHO指令的时候,服务器将显示如下列表:
|
|
|
@@ -199,6 +208,7 @@ User CHRIS is 1
|
|
|
下边这个版本的 simple_tcp_server.go 从很多方面优化了第一个tcp服务器的示例 server.go 并且拥有更好的结构,它只用了80行代码!
|
|
|
|
|
|
示例 15.5 [simple_tcp_server.go](examples/chapter_15/simple_tcp_server.go):
|
|
|
+
|
|
|
```go
|
|
|
// Simple multi-thread/multi-core TCP server.
|
|
|
package main
|
|
|
@@ -286,7 +296,9 @@ func checkError(error error, info string) {
|
|
|
(**译者注:应该是由于go版本的更新,会提示os.EAGAIN undefined ,修改后的代码:[simple_tcp_server_v1.go](examples/chapter_15/simple_tcp_server_v1.go)**)
|
|
|
|
|
|
都有哪些改进?
|
|
|
+
|
|
|
* 服务器地址和端口不再是硬编码,而是通过命令行传入参数并通过`flag`包来读取这些参数。这里使用了`flag.NArg()`检查是否按照期望传入了2个参数:
|
|
|
+
|
|
|
```go
|
|
|
if flag.NArg() != 2{
|
|
|
panic("usage: host port")
|