windows - 在 Windows 上使用套接字

标签 windows sockets go posix

我目前正在使用 go 开发一个服务器/客户端项目,我需要在没有 net 包的情况下使用套接字。所以我使用在 syscall 包上创建的 POSIX 函数。我的服务器程序在 Linux 上,我的客户端程序在 Windows (8) 上。

基本上,我想将客户端连接到服务器。问题是当客户端想要在套接字中写入时,它会显示“ fatal error :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)
    }
}

(对不起,如果我的英语不好,我是法国人)

最佳答案

正如 JimB 提到的,在 Windows 上 WSASend用于通过网络发送数据。

基本上,您必须对客户端代码进行更改的是:

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

至:

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)

关于windows - 在 Windows 上使用套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34073103/

相关文章:

windows - 分析msvcr80.dll中的应用程序故障,故障地址0x00008aa0

json - golang GET请求运行时json类型错误

javascript - 套接字 : Get Client sessionID at any point

java - 关闭一个套接字会关闭所有套接字,Java

go - 将 cmd stdout 和 stderr 作为字符串返回,而不是在 golang 中打印到控制台

go - 将数据写入 go lang channel 的成本?

windows - Webpack 13详细堆栈错误: my-project@1. 0.0构建:webpack --mode development

android - 如何在执行阶段(Windows)中从Gradle构建运行exe文件

windows - 相当于带引号的 Unix 参数扩展的批处理文件

c - 多线程 epoll