承认吧,你肯定也会有深夜寂寞时特别想找人聊天但翻遍朋友圈,却还是没有发现合适的人的时候,今天我们就来写一个随机配对聊天程序,解决广大单身狗寂寞时想要找人聊天的需求吧。
为了让聊天不那么 gay ,我们的聊天程序会让异性匹配聊天,用户通过客户端连接到聊天程序服务器 localhost:8080 ,例如使用 netcat 通过 nc localhost 8080 命令连接聊天程序服务器,服务器会根据你的性别匹配异性聊天。
在实现方面,为了达到异性相互聊天的目标,我们创建两个通道,分别是 boy 通道和 girl 通道,并通过 net.Listen 方法监听 8080 端口,对于每个连接我们起一个 goroutine 进行匹配操作。
1 | var boy = make(chan io.ReadWriteCloser) |
match 方法会首先询问你的性别,如果是男生则匹配女生聊天,反之亦然。如果当前只有一个男生连进来,程序会执行第一个 select 中的 case boy <- c: 条件,由于 boy 通道是 unbuffered channel ,直到有女生进来之前该操作都会阻塞。如果此时进来一个女生,程序会执行第二个select 操作,由于 girl 通道也是 unbuffered channel ,所以case girl <- c: 语句也会阻塞,但此时 case p := <-boy: 会被执行,这时候就可以通过 chat 方法让两个 net.Conn 相互交流了。match 方法实现的逻辑就达到了异性交流的目的了。
1 | func match(c io.ReadWriteCloser) { |
上面的 chat 方法依赖 cp 方法 ,该方法封装了 io.Copy 方法,主要就是为了当任意一方结束聊天时发送一个 err 到我们的 errc ,以关闭双方的连接。
1 | func cp(w io.Writer, r io.Reader, errc chan<- error) { |
chat 方法通过两个 goroutine ,go cp(a, b, errc) 和 go cp(b, a, errc) 使a和b这两个 net.Conn 相互发送消息,如果任意一方结束聊天, errc 通道就会返回一个 error 值,a和b就会被关闭,此时聊天结束。
1 | func chat(a, b io.ReadWriteCloser) { |