Skip to content

Instantly share code, notes, and snippets.

@furu
Last active August 29, 2015 14:05
Show Gist options
  • Save furu/dde894cc059bfd2c5c12 to your computer and use it in GitHub Desktop.
Save furu/dde894cc059bfd2c5c12 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"log"
"net"
"os"
"os/signal"
"reflect"
"syscall"
)
func handleTCPClient(conn net.Conn) {
defer conn.Close()
// http://naoina.plog.la/2013/11/12/235753683181
// http://walf443.hatenablog.com/entry/2014/05/13/105216
fdValue := reflect.Indirect(reflect.Indirect(reflect.ValueOf(conn)).FieldByName("fd"))
fd := fdValue.FieldByName("sysfd").Int()
syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_SETOWN, uintptr(os.Getpid()))
go func() {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGURG)
for {
log.Println("^o^ < Waiting for signal")
sig := <-c // シグナルが発生するまでブロックされる
switch sig {
case syscall.SIGURG:
log.Println("^o^ = ^o^ < Occuring a signal!: ", sig)
// OOB データは 1byte しか受け取れない?
oobData := make([]byte, 1)
n, _, err := syscall.Recvfrom(int(fd), oobData, syscall.MSG_OOB)
if err != nil {
log.Fatalln(err)
}
fmt.Printf("Recieved OOB data '%s' (%d byte)\n", oobData, n)
}
}
}()
for {
mess := make([]byte, 256)
_, err := conn.Read(mess) // OOBデータを受け取って、上のシグナルハンドラーを実行した後に、ここでブロックしている?
if err != nil {
log.Println(err)
break
}
fmt.Println(string(mess))
}
log.Printf("Finish handling %v\n", conn.RemoteAddr())
}
func main() {
listener, err := net.Listen("tcp", net.JoinHostPort("localhost", "4545"))
if err != nil {
log.Fatalln(err)
}
defer listener.Close()
log.Printf("Listening on %v\n", listener.Addr())
for {
conn, err := listener.Accept()
if err != nil {
log.Println(err)
continue
}
log.Printf("Handling Client %v\n", conn.RemoteAddr())
go handleTCPClient(conn)
}
}
// syscall
//
// func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error)
//
// func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, err error)
package main
import (
"fmt"
"log"
"net"
"os"
"os/signal"
"reflect"
"syscall"
"time"
)
func main() {
conn, err := net.Dial("tcp", net.JoinHostPort("localhost", "4545"))
if err != nil {
log.Fatalln(err)
}
defer conn.Close()
log.Printf("Connected to %v\n", conn.RemoteAddr())
go func() {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
for {
sig := <-c // シグナルが発生するまでブロックされる
switch sig {
case os.Interrupt:
// http://naoina.plog.la/2013/11/12/235753683181
// http://walf443.hatenablog.com/entry/2014/05/13/105216
fdValue := reflect.Indirect(reflect.Indirect(reflect.ValueOf(conn)).FieldByName("fd"))
fd := int(fdValue.FieldByName("sysfd").Int())
to, err := syscall.Getpeername(fd)
if err != nil {
log.Fatalln(err)
}
// OOB データは 1byte しか送れない?
// 受信側では、256byte 分のバッファを用意して、^o^ というメッセージを送ったが、
// ^ しか受け取れなかった。
oobData := []byte("!")
err = syscall.Sendto(fd, oobData, syscall.MSG_OOB, to)
if err != nil {
log.Fatalln(err)
}
log.Println("Sent OOB data")
}
}
}()
for i := 0; i < 30; i++ {
fmt.Fprint(conn, i)
log.Println("Sent: ", i)
time.Sleep(1 * time.Second)
}
log.Printf("Disconnected from %v\n", conn.RemoteAddr())
}
// syscall
//
// func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (err error)
//
// func SendmsgN(fd int, p, oob []byte, to Sockaddr, flags int) (n int, err error)
//
// func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error)
//
// Sockaddr型はインタフェースだけれど、何を実装すればよいのか公開されていない
//
// type Sockaddr interface {
// // contains filtered or unexported methods
// }
//
// Sockaddr のドキュメントの下に、Getpeername() と Getsockname() という関数があって、
// どちらもファイルディスクリプタを引数に取って、Sockaddr型を返すようになっている。
//
// func Getpeername(fd int) (sa Sockaddr, err error)
// func Getsockname(fd int) (sa Sockaddr, err error)
//
// 違いがよくわからなくてどちらを使えばよいのかわからないが、とりあえず Sockaddr型が欲しいので、
// どっちかを使う。
//
//
// OOBデータ - out-of-band data
//
// * 名前から、普通のデータストリームの外側から送られてくるように思えるけれど、そうではないらしい。
// * 1度に1byteだけ送ることができるらしい。複数(多バイト?)送った場合、最後のものが受け取られる?
// * one urgent pointer per stream
@furu
Copy link
Author

furu commented Sep 2, 2014

oob_reciever.go が期待する動作にならない…

$ go run oob_reciever.go

// result
2014/09/02 20:26:46 Listening on 127.0.0.1:4545
2014/09/02 20:26:57 Handling Client 127.0.0.1:64410
0
2014/09/02 20:26:57 ^o^ < Waiting for signal
1
2
3
4
5
6
7
2014/09/02 20:27:05 ^o^ = ^o^ < Occuring a signal!:  urgent I/O condition
Recieved OOB data '!' (1 byte)
2014/09/02 20:27:05 ^o^ < Waiting for signal
8
2014/09/02 20:27:19 ^o^ = ^o^ < Occuring a signal!:  urgent I/O condition
Recieved OOB data '!' (1 byte)
2014/09/02 20:27:19 ^o^ < Waiting for signal
9101112131415161718192021
22
23242526272829
2014/09/02 20:27:27 EOF
2014/09/02 20:27:27 Finish handling 127.0.0.1:64410



// expected
2014/09/02 20:26:46 Listening on 127.0.0.1:4545
2014/09/02 20:26:57 Handling Client 127.0.0.1:64410
0
2014/09/02 20:26:57 ^o^ < Waiting for signal
1
2
3
4
5
6
7
2014/09/02 20:27:05 ^o^ = ^o^ < Occuring a signal!:  urgent I/O condition
Recieved OOB data '!' (1 byte)
2014/09/02 20:27:05 ^o^ < Waiting for signal
8
2014/09/02 20:27:19 ^o^ = ^o^ < Occuring a signal!:  urgent I/O condition
Recieved OOB data '!' (1 byte)
2014/09/02 20:27:19 ^o^ < Waiting for signal
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2014/09/02 20:27:27 EOF
2014/09/02 20:27:27 Finish handling 127.0.0.1:64410
$ go run oob_sender.go

2014/09/02 20:26:57 Connected to 127.0.0.1:4545
2014/09/02 20:26:57 Sent:  0
2014/09/02 20:26:58 Sent:  1
2014/09/02 20:26:59 Sent:  2
2014/09/02 20:27:00 Sent:  3
2014/09/02 20:27:01 Sent:  4
2014/09/02 20:27:02 Sent:  5
2014/09/02 20:27:03 Sent:  6
2014/09/02 20:27:04 Sent:  7
^C2014/09/02 20:27:05 Sent OOB data
2014/09/02 20:27:05 Sent:  8
2014/09/02 20:27:06 Sent:  9
2014/09/02 20:27:07 Sent:  10
2014/09/02 20:27:08 Sent:  11
2014/09/02 20:27:09 Sent:  12
2014/09/02 20:27:10 Sent:  13
2014/09/02 20:27:11 Sent:  14
2014/09/02 20:27:12 Sent:  15
2014/09/02 20:27:13 Sent:  16
2014/09/02 20:27:14 Sent:  17
2014/09/02 20:27:15 Sent:  18
2014/09/02 20:27:16 Sent:  19
2014/09/02 20:27:17 Sent:  20
2014/09/02 20:27:18 Sent:  21
^C2014/09/02 20:27:19 Sent OOB data
2014/09/02 20:27:19 Sent:  22
2014/09/02 20:27:20 Sent:  23
2014/09/02 20:27:21 Sent:  24
2014/09/02 20:27:22 Sent:  25
2014/09/02 20:27:23 Sent:  26
2014/09/02 20:27:24 Sent:  27
2014/09/02 20:27:25 Sent:  28
2014/09/02 20:27:26 Sent:  29
2014/09/02 20:27:27 Disconnected from 127.0.0.1:4545

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment