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)