go tcp server

weiwenwang · 2018-04-23 21:43:16 · 1792 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2018-04-23 21:43:16 的主题,其中的信息可能已经有所发展或是发生改变。

  listener, err := net.Listen("tcp", "127.0.0.1:7777")
    checkError(err)
    fmt.Println("建立成功!")
    ch := make(chan string)
    for {
        //等待客户端接入
        conn, err := listener.Accept()
    ....

我想在客户端建立连接的时候,把用户作为key,conn作为value,存在数据库或者redis里面,当想往某个用户发数据的时候,直接用户用户找到该用户的conn,如何实现呢


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1792 次点击  
加入收藏 微博
7 回复  |  直到 2018-04-25 17:43:56
king129
king129 · #1 · 7年之前

map

dong-hao
dong-hao · #2 · 7年之前

问题还是有点意思的,可以考虑用 chan 来实现这个,下面是我写的代码,可以参考着写个更完善的。

package main

import (
    "bufio"
    "fmt"
    "io"
    "net"
    "os"
)

func main() {
    l, _ := net.Listen("tcp", ":8000")
    for {
        conn, _ := l.Accept()
        ch := make(chan string)
        go talk(conn, ch)
        go input(ch)
    }
}

func talk(conn io.ReadWriteCloser, ch chan string) {
    for c := range ch {
        fmt.Fprintf(conn, c)
    }
    fmt.Fprintf(conn, "closed, byebye.")
    conn.Close()
}

func input(ch chan string) {
    reader := bufio.NewReader(os.Stdin)
    text, _ := reader.ReadString('\n')
    for text != "#\n" {
        ch <- text
        text, _ = reader.ReadString('\n')
    }
    close(ch)
}
terender
terender · #3 · 7年之前

为什么要存数据库或者redis?

用户的连接是实时的,一旦断开就失效了,下次连接就是新的,你就存在内存的一个map里就可以。

存数据库或者redis的话,只可能存 conn 的内存地址,或者更底层的 socket fd, 但不管是哪个,在用户断开连接之后都会失效。

使用失效的内存地址作为指针获取conn会导致野指针访问,使用失效的 socket fd 如果这个fd号没被重用还好,被重用了你就把消息发给错误的人了

Titanarthas
Titanarthas · #4 · 7年之前

通常来说,用map。 然后要注意处理用户上线下线的情况。

weiwenwang
weiwenwang · #5 · 7年之前
terenderterender #3 回复

为什么要存数据库或者redis? 用户的连接是实时的,一旦断开就失效了,下次连接就是新的,你就存在内存的一个map里就可以。 存数据库或者redis的话,只可能存 conn 的内存地址,或者更底层的 socket fd, 但不管是哪个,在用户断开连接之后都会失效。 使用失效的内存地址作为指针获取conn会导致野指针访问,使用失效的 socket fd 如果这个fd号没被重用还好,被重用了你就把消息发给错误的人了

我在写c/swoole的时候,每个连接都是一个fd,我可以把这个fd存在外部,当某台机器要发消息给uid1这个用户,就可以到redis里面找这个人在哪台机器,fd是多少,就可以通知这台机器发消息了,我看conn是内存地址,这个肯定是存不了

我可以把uid作为key, conn作为value存map里面,然后在redis里面存uid在哪套机器上,找到机器后,在通过uid找conn

terender
terender · #6 · 7年之前
weiwenwangweiwenwang #5 回复

#3楼 @terender 我在写c/swoole的时候,每个连接都是一个fd,我可以把这个fd存在外部,当某台机器要发消息给uid1这个用户,就可以到redis里面找这个人在哪台机器,fd是多少,就可以通知这台机器发消息了,我看conn是内存地址,这个肯定是存不了 我可以把uid作为key, conn作为value存map里面,然后在redis里面存uid在哪套机器上,找到机器后,在通过uid找conn

存在外部没问题,但是一旦远端中断了tcp连接,这个fd就失效了。

weiwenwang
weiwenwang · #7 · 7年之前
terenderterender #6 回复

#5楼 @weiwenwang 存在外部没问题,但是一旦远端中断了tcp连接,这个fd就失效了。

明白, 如果客户端或者服务器正常关闭,那么一定会更新外部的数据的,如果客户端不正常关闭,服务器端心跳机制也会去更新的, 我是这样计划的,你的意思conn可以存外部,怎么存,你觉得我上面那种外部+内部的方法可行不

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传