一.概述

  • 点对点通信就是客户端A发送消息给服务端,再由服务端把消息传递给客户端B.相同道理客户端B想给客户端A发送消息也需要把消息传递给服务端,再由服务端把消息传递给A
  • 正常情况下客户端A和客户端B可以通过用户名、IP等唯一身份标识区分每个用户.在本功能练习中要求客户端先注册用户名,然后告诉服务端给谁发消息.如果用户名存在不允许注册
  • 在本功能练习中用户信息存储到临时容器map中,没有进行持久化操作.

    二.代码实现

  • 项目结构如下

    1. --项目名
    2. --src
    3. --client
    4. client.go
    5. --server
    6. server.go
    7. main.go
  • 在server.go中编写代码 ```go package main

import ( “net” “fmt” “strings” )

type User struct { Username string OtherUsername string Msg string ServerMsg string }

var ( userMap = make(map[string]net.Conn) user = new(User) )

func main() { addr, := net.ResolveTCPAddr(“tcp4”, “:9999”) lis, := net.ListenTCP(“tcp4”, addr)

  1. for {
  2. conn, _ := lis.Accept()
  3. go func() {
  4. for {
  5. b := make([]byte, 512)
  6. //读取数据
  7. count, _ := conn.Read(b)
  8. arrStr := strings.Split(string(b[:count]), "-")
  9. user.Username = arrStr[0]
  10. user.OtherUsername = arrStr[1]
  11. user.Msg = arrStr[2]
  12. user.ServerMsg = arrStr[3]
  13. userMap[user.Username] = conn
  14. if v, ok := userMap[user.OtherUsername]; ok && v != nil {
  15. user.ServerMsg = ""
  16. n, e := v.Write([]byte(fmt.Sprintf("%s-%s-%s-%s", user.Username, user.OtherUsername, user.Msg, user.ServerMsg)))
  17. if n == 0 || e != nil {
  18. conn.Close()
  19. delete(userMap, user.OtherUsername)
  20. break
  21. }
  22. } else {
  23. user.ServerMsg = "对方不在线"
  24. n, e := conn.Write([]byte(fmt.Sprintf("%s-%s-%s-%s", user.Username, user.OtherUsername, user.Msg, user.ServerMsg)))
  25. }
  26. }
  27. }()
  28. }

}

  1. - client.go中编写代码
  2. ```go
  3. package main
  4. import (
  5. "net"
  6. "fmt"
  7. "sync"
  8. "os"
  9. "strings"
  10. )
  11. type User struct {
  12. Username string
  13. OtherUsername string
  14. Msg string
  15. ServerMsg string
  16. }
  17. var (
  18. user = new(User)
  19. wg sync.WaitGroup
  20. )
  21. func main() {
  22. wg.Add(1)
  23. fmt.Println("请登录,输入用户名:")
  24. fmt.Scanln(&user.Username)
  25. fmt.Println("请输入要给谁发送消息")
  26. fmt.Scanln(&user.OtherUsername)
  27. addr, _ := net.ResolveTCPAddr("tcp4", ":9999")
  28. conn, _ := net.DialTCP("tcp4", nil, addr)
  29. go func() {
  30. fmt.Print("请输入:(只提示一次,以后直接输入即可)")
  31. for {
  32. fmt.Scanln(&user.Msg)
  33. if user.Msg == "exit" {
  34. conn.Close()
  35. wg.Done()
  36. os.Exit(0)
  37. }
  38. conn.Write([]byte(fmt.Sprintf("%s-%s-%s-%s", user.Username, user.OtherUsername, user.Msg, user.ServerMsg)))
  39. }
  40. }()
  41. go func() {
  42. for {
  43. rb := make([]byte, 512)
  44. c, _ := conn.Read(rb)
  45. user2 := new(User)
  46. arrStr := strings.Split(string(rb[:c]), "-")
  47. user2.Username = arrStr[0]
  48. user2.OtherUsername = arrStr[1]
  49. user2.Msg = arrStr[2]
  50. user2.ServerMsg = arrStr[3]
  51. if user2.ServerMsg != "" {
  52. fmt.Println("\t\t\t服务器消息:", user2.ServerMsg)
  53. } else {
  54. fmt.Println("\t\t\t", user2.Username, ":", user2.Msg)
  55. }
  56. }
  57. }()
  58. wg.Wait()
  59. }