【发布时间】:2015-12-04 05:58:30
【问题描述】:
我目前正在使用 go 开发一个服务器/客户端项目,我需要在没有 net 包的情况下使用套接字。所以我使用我在 syscall 包上创建的 POSIX 函数。我的服务器程序在 Linux 上,我的客户端在 Windows (8) 上。
所以基本上,我想将客户端连接到服务器。问题是当客户端想要写入套接字时,它会显示“致命错误:windows 不支持”。
客户:
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)
}
}
服务器(运行良好):
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)
}
}
(对不起,如果我的英语不好,我是法国人)
【问题讨论】:
-
你为什么要绕过
net包?这使您的程序不可移植,因为 windows 和 linux 使用不同的系统调用来操作套接字。 -
为了简单起见,我的老师想要它。 ://
-
这远非简单,但也许是一种学习体验。阅读 net 包中的 windows 特定代码,它已经为你完成了(提示,windows 不使用套接字上的
write系统调用) -
是的,正如您所说,这是一次学习经历。目的是使用 POSIX 库。
-
除了windows socket api 肯定不是posix。