Use socket with windows

huangapple go评论113阅读模式
英文:

Use socket with windows

问题

我目前正在使用Go语言开发一个服务器/客户端项目,需要在没有net包的情况下使用套接字。因此,我使用了在syscall包中找到的POSIX函数。我的服务器程序在Linux上运行,客户端在Windows 8上运行。

基本上,我想要将客户端连接到服务器。问题是,当客户端想要在套接字中写入数据时,它显示"致命错误:Windows不支持"。

客户端代码:

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "runtime"
  6. s "syscall"
  7. )
  8. const (
  9. MAXSIZE = 500
  10. PORT = 3000
  11. )
  12. var (
  13. ADDR = [4]byte{10, 8, 0, 1}
  14. )
  15. func Dial() (s.Handle, s.SockaddrInet4, error) {
  16. var sa s.SockaddrInet4 = s.SockaddrInet4{Port: PORT, Addr: ADDR}
  17. var d s.WSAData
  18. var sd s.Handle
  19. // 之前的错误提示我这样做
  20. if runtime.GOOS == "windows" {
  21. err := s.WSAStartup(uint32(0x202), &d)
  22. if err != nil {
  23. return sd, sa, err
  24. }
  25. }
  26. sd, err := s.Socket(s.AF_INET, s.SOCK_STREAM, 0)
  27. if err != nil {
  28. return sd, sa, err
  29. }
  30. s.Connect(sd, &sa)
  31. return sd, sa, err
  32. }
  33. func main() {
  34. sd, sa, err := Dial()
  35. check(err)
  36. defer s.Close(sd)
  37. _, err = s.Write(sd, make([]byte, 500, 42))
  38. check(err)
  39. }
  40. func check(err error) {
  41. if err != nil {
  42. fmt.Fprintf(os.Stderr, "致命错误:%s", err.Error())
  43. os.Exit(1)
  44. }
  45. }

服务器代码(正常工作):

  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. s "syscall"
  7. )
  8. const (
  9. PORT = 3000
  10. )
  11. func main() {
  12. var sa s.SockaddrInet4
  13. fmt.Println(sa)
  14. fd, err := s.Socket(s.AF_INET, s.SOCK_STREAM, 0)
  15. if err != nil {
  16. check(err)
  17. }
  18. defer s.Close(fd)
  19. if err := s.Bind(fd, &s.SockaddrInet4{Port: PORT, Addr: [4]byte{0, 0, 0, 0}}); err != nil {
  20. check(err)
  21. }
  22. if err := s.Listen(fd, 5); err != nil {
  23. check(err)
  24. }
  25. for {
  26. nfd, sa, err := s.Accept(fd)
  27. if err != nil {
  28. check(err)
  29. }
  30. go func(nfd int, sa s.Sockaddr) {
  31. var n int
  32. fmt.Println(sa)
  33. defer s.Close(nfd)
  34. b := make([]byte, 500)
  35. n, err = s.Read(nfd, b)
  36. check(err)
  37. fmt.Println(n)
  38. }(nfd, sa)
  39. }
  40. }
  41. func check(err error) {
  42. if err != nil {
  43. fmt.Fprintf(os.Stderr, "致命错误:%s", err.Error())
  44. os.Exit(1)
  45. }
  46. }

希望对你有帮助!

英文:

I'm currently working on a server/client project with go where I need to work with sockets without the net package. So I use POSIX functions I founded on syscall package. My server program in on Linux and my client in on Windows (8).

So basically, I want to connect the client to the server. The problem is when the client wants to Write in the socket it says "Fatal error : not supported by windows".

Client :

  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "runtime"
  6. s "syscall"
  7. )
  8. const (
  9. MAXSIZE = 500
  10. PORT = 3000
  11. )
  12. var (
  13. ADDR = [4]byte{10, 8, 0, 1}
  14. )
  15. func Dial() (s.Handle, s.SockaddrInet4, error) {
  16. var sa s.SockaddrInet4 = s.SockaddrInet4{Port: PORT, Addr: ADDR}
  17. var d s.WSAData
  18. var sd s.Handle
  19. // a previous error told me to this
  20. if runtime.GOOS == "windows" {
  21. err := s.WSAStartup(uint32(0x202), &d)
  22. if err != nil {
  23. return sd, sa, err
  24. }
  25. }
  26. sd, err := s.Socket(s.AF_INET, s.SOCK_STREAM, 0)
  27. if err != nil {
  28. return sd, sa, err
  29. }
  30. s.Connect(sd, &sa)
  31. return sd, sa, err
  32. }
  33. func main() {
  34. sd, sa, err := Dial()
  35. check(err)
  36. defer s.Close(sd)
  37. _, err = s.Write(sd, make([]byte, 500,42))
  38. check(err)
  39. }
  40. func check(err error) {
  41. if err != nil {
  42. fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
  43. os.Exit(1)
  44. }
  45. }

Server (works well) :

  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. s "syscall"
  7. )
  8. const (
  9. PORT = 3000
  10. )
  11. func main() {
  12. var sa s.SockaddrInet4
  13. fmt.Println(sa)
  14. fd, err := s.Socket(s.AF_INET, s.SOCK_STREAM, 0)
  15. if err != nil {
  16. check(err)
  17. }
  18. defer s.Close(fd)
  19. if err := s.Bind(fd, &s.SockaddrInet4{Port: PORT, Addr: [4]byte{0, 0, 0, 0}}); err != nil {
  20. check(err)
  21. }
  22. if err := s.Listen(fd, 5); err != nil {
  23. check(err)
  24. }
  25. for {
  26. nfd, sa, err := s.Accept(fd)
  27. if err != nil {
  28. check(err)
  29. }
  30. go func(nfd int, sa s.Sockaddr) {
  31. var n int
  32. fmt.Println(sa)
  33. defer s.Close(nfd)
  34. b := make([]byte, 500)
  35. n, err = s.Read(nfd, b)
  36. check(err)
  37. fmt.Println(n)
  38. }(nfd, sa)
  39. }
  40. }
  41. func check(err error) {
  42. if err != nil {
  43. fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
  44. os.Exit(1)
  45. }
  46. }

(Sry if my english is bad, I'm French)

答案1

得分: 2

像JimB提到的那样,在Windows上使用WSASend来发送网络数据。

所以基本上,你需要在客户端代码中进行以下更改:

  1. _, err = s.Write(sd, make([]byte, 500,42))

改为:

  1. data := make([]byte, 4)
  2. buf := &s.WSABuf{
  3. Len: uint32(len(data)),
  4. Buf: &data[0],
  5. }
  6. var sent *uint32
  7. overlapped := s.Overlapped{}
  8. croutine := byte(0)
  9. err = s.WSASendto(sd, buf, 1, sent, uint32(0), &sa, &overlapped, &croutine)
  10. check(err)
英文:

Like JimB mentioned, on Windows WSASend is used to send data over the network.

So basically, what you have to change on your client code is:

  1. _, err = s.Write(sd, make([]byte, 500,42))

to:

  1. data := make([]byte, 4)
  2. buf := &s.WSABuf{
  3. Len: uint32(len(data)),
  4. Buf: &data[0],
  5. }
  6. var sent *uint32
  7. overlapped := s.Overlapped{}
  8. croutine := byte(0)
  9. err = s.WSASendto(sd, buf, 1, sent, uint32(0), &sa, &overlapped, &croutine)
  10. check(err)

huangapple
  • 本文由 发表于 2015年12月4日 02:03:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/34073103.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定