在Windows上使用套接字

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 :

    package main

import (
    "fmt"
    "os"
    "runtime"
    s "syscall"
)

const (
    MAXSIZE = 500
    PORT    = 3000
)

var (
    ADDR = [4]byte{10, 8, 0, 1}
)

func Dial() (s.Handle, s.SockaddrInet4, error) {
    var sa s.SockaddrInet4 = s.SockaddrInet4{Port: PORT, Addr: ADDR}
    var d s.WSAData
    var sd s.Handle

    // a previous error told me to this
    if runtime.GOOS == "windows" {
        err := s.WSAStartup(uint32(0x202), &d)
        if err != nil {
            return sd, sa, err
        }
    }

    sd, err := s.Socket(s.AF_INET, s.SOCK_STREAM, 0)
    if err != nil {
        return sd, sa, err
    }

    s.Connect(sd, &sa)
    return sd, sa, err
}

func main() {
    sd, sa, err := Dial()
    check(err)
    defer s.Close(sd)

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

func check(err error) {
    if err != nil {
        fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
        os.Exit(1)
    }
}

Server (works well) :

    package main

import (
    "fmt"
    "io/ioutil"
    "os"
    s "syscall"
)

const (
    PORT = 3000
)

func main() {
    var sa s.SockaddrInet4
    fmt.Println(sa)
    fd, err := s.Socket(s.AF_INET, s.SOCK_STREAM, 0)
    if err != nil {
        check(err)
    }
    defer s.Close(fd)
    if err := s.Bind(fd, &s.SockaddrInet4{Port: PORT, Addr: [4]byte{0, 0, 0, 0}}); err != nil {
        check(err)
    }

    if err := s.Listen(fd, 5); err != nil {
        check(err)
    }

    for {
        nfd, sa, err := s.Accept(fd)
        if err != nil {
            check(err)
        }

        go func(nfd int, sa s.Sockaddr) {
            var n int

            fmt.Println(sa)
            defer s.Close(nfd)

            b := make([]byte, 500)
            n, err = s.Read(nfd, b)
            check(err)
            fmt.Println(n)

        }(nfd, sa)
    }
}

func check(err error) {
    if err != nil {
        fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
        os.Exit(1)
    }
}

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

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:

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

to:

data := make([]byte, 4)
buf := &s.WSABuf{
    Len: uint32(len(data)),
    Buf: &data[0],
}
var sent *uint32
overlapped := s.Overlapped{}
croutine := byte(0)

err = s.WSASendto(sd, buf, 1, sent, uint32(0), &sa, &overlapped, &croutine)
check(err)