socket programming, getting getsockopt: connection refused - sockets

I'm having trouble with socket programming.
I have a program that reads from localhost:7777 and writes to localhost:8000.
I use netcat from the command line to write and read to 7777 and 8000 respectively.
This is the reader:
netcat -l -p 8000
And this is the writer:
printf "asti||" | netcat localhost 7777
But my program gets network errors when it tries to write to port 8000 for the second
time. The error is Fatal error: dial tcp 127.0.0.1:8000: getsockopt: connection refused.
What's happening? Why on the second write the error appears?
Furthermore, I noticed that if I kill the netcat reader and restart it then there's no network errors. So to reiterate, the program writes once to 8000 and netcat reads it. Then I kill netcat reader and restart it. At this point the program can write again to 8000. But if the program tries to write two successive times to 8000 without me restarting netcat, then the error appears.
Here is the entire program (it's short). If you like, you experience this mystical behaviour yourself:
package main
import (
"fmt"
"net"
"os"
"strings"
// "io/ioutil"
)
func main() {
end_of_message_terminator := "||"
beginning_of_next_message := ""
request := make([]byte, 512)
service_port := ":7777"
tcpAddr, err := net.ResolveTCPAddr("tcp4", service_port)
checkError(err)
listener, err := net.ListenTCP("tcp", tcpAddr)
checkError(err)
for {
conn, err := listener.Accept()
if err != nil {
continue
}
read_len, err := conn.Read(request)
if read_len == 0 {
continue
}
request_string := string(request[:read_len])
fmt.Printf("Request String %s\\END", request_string)
messages := strings.Split(request_string, end_of_message_terminator)
fmt.Printf("%q\n", messages)
messages[0] = beginning_of_next_message + messages[0]
if messages[len(messages) - 1] != "" {
beginning_of_next_message = messages[len(messages) - 1]
messages[len(messages) - 1] = ""
fmt.Printf("was here 00\n")
}
if len(messages) == 1 {
continue
}
for i := range messages {
go func(){
fmt.Printf("was here 04\n")
respond_to_message(messages[i])
}()
fmt.Printf("was here 01\n")
}
conn.Close()
}
}
func respond_to_message(message string){
message_parameters := strings.Split(message, "|")
response_port := "localhost:8000"
tcpAddr_res, err := net.ResolveTCPAddr("tcp4", response_port)
checkError(err)
response_writer, err := net.DialTCP("tcp", nil, tcpAddr_res)
for i := range message_parameters {
fmt.Printf("was here03\n")
param_parts := strings.Split(message_parameters[i], "=")
fmt.Printf("message: %s\n", message)
fmt.Printf("message_parameters%q\n", message_parameters)
fmt.Printf("params_parts: %q\n", param_parts)
//param_name := param_parts[0]
//param_value := param_parts[1]
checkError(err)
response_writer.Write([]byte("asti de crhis"))
checkError(err)
//result, err := ioutil.ReadAll(response_writer)
//checkError(err)
//fmt.Println(string(result))
}
//response_writer.Close()
}
func checkError(err error) {
if err != nil {
fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
os.Exit(1)
}
}

Related

Execute powershell command in running container via Docker API

I want to execute a powershell command in a docker container running on a windows host.
The specific command I want to execute is "powershell Get-PSDrive C | Select-Object Used,Free"
I have implemented this using the Docker API for python and it is simple like calling:
cmd = "powershell Get-PSDrive C | Select-Object Used,Free"
output = container.exec_run(cmd)
This works as intended, but I need to implement this in golang.
But somehow, it is not clear for me how to interact with the Docker API for golang. I looked into the API and was confused by the hijackedSession. How do I have to setup the calls for ContainerExecCreate, ContainerExecAttach and ContainerExecStart ?
I expect the golang script to deliver the same results like the python code does:
Used Free
---- ----
199181606912 307151622144
Which then can be parsed by me.
The HijackedResponse struct:
type HijackedResponse struct {
Conn net.Conn
Reader *bufio.Reader
}
You need to copy the response from the resp.Reader,here is my code:
package main
import (
"bytes"
"context"
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/docker/docker/pkg/stdcopy"
"strings"
)
func readFromCommand() (string, error) {
cli, err := client.NewEnvClient()
if err != nil {
return "", err
}
ctx := context.Background()
config := types.ExecConfig{
Cmd: strings.Split("powershell Get-PSDrive C | Select-Object Used,Free", " "),
AttachStdout: true,
AttachStderr: true,
}
response, err := cli.ContainerExecCreate(ctx,
// container id
"cf59d65ab1", config)
if err != nil {
return "", err
}
execID := response.ID
resp, err := cli.ContainerExecAttach(ctx, execID, config)
if err != nil {
return "", err
}
defer resp.Close()
stdout := new(bytes.Buffer)
stderr := new(bytes.Buffer)
_, err = stdcopy.StdCopy(stdout, stderr, resp.Reader)
if err != nil {
return "", err
}
s := stdout.String()
fmt.Println(s)
i := stderr.String()
fmt.Println(i)
return s, nil
}
Do remember to change the container id.

when does Go http.Get reuse the tcp connection?

in GO net/http Response Body annotation says:
It is the caller's responsibility to close Body. The default HTTP client's Transport does not attempt to reuse HTTP/1.0 or HTTP/1.1 TCP connections ("keep-alive") unless the Body is read to completion and is
closed.
It's mean: if I use http.Get and don't call resp.Body.Close() then it will not resue HTTP/1.0 or HTTP/1.1 TCP connections ("keep-alive") yeah?
so I write some code:
package main
import (
"time"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
resp, err := http.Get("http://127.0.0.1:8588")
if err != nil {
panic(err)
}
_, err = ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
resp2, err := http.Get("http://127.0.0.1:8588")
if err != nil {
panic(err)
}
_, err = ioutil.ReadAll(resp2.Body)
if err != nil {
panic(err)
}
fmt.Println("before time sleep")
time.Sleep(time.Second * 35)
}
and I only see ONE tcp connection build in wireshark, why?
I don't close res.Body so the http client should't be reuse the tcp connection.
this problem has been solved in
https://github.com/golang/go/issues/22954.
You have read it till the end in first occurence of line:
_, err = ioutil.ReadAll(resp.Body)
So the connection is ready to be resused. Try not to read and run again.

SSL Socket client in Golang

I'm trying to connect to a server through a socket using an ssl certificate. I have the private key and the certificate needed to connect to the server, i have looked around for something to help me write this code in Go but i have not found anything helpful. Here is the code i write so far, but it does not seem to get me anywhere, it seems to be sending data(tls.dial) before getting to the actual data, which forces the server to reply with some encrypted data which i am unable to check.
func main() {
cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
if err != nil {
log.Fatalf("server: loadkeys: %s", err)
}
config := tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true}
conn, err := tls.Dial("tcp", "1.2.3.4:1234", &config)
if err != nil {
log.Fatalf("client: dial: %s", err)
}
defer conn.Close()
log.Println("client: connected to: ", conn.RemoteAddr())
state := conn.ConnectionState()
for _, v := range state.PeerCertificates {
fmt.Println(x509.MarshalPKIXPublicKey(v.PublicKey))
fmt.Println(v.Subject)
}
log.Println("client: handshake: ", state.HandshakeComplete)
log.Println("client: mutual: ", state.NegotiatedProtocolIsMutual)
message := "data"
n, err := io.WriteString(conn, message)
if err != nil {
log.Fatalf("client: write: %s", err)
}
log.Printf("client: wrote %q (%d bytes)", message, n)
reply := make([]byte, 256)
n, err = conn.Read(reply)
log.Printf("client: read %q (%d bytes)", string(reply[:n]), n)
log.Print("client: exiting")
}

Go writing to socket - invalid argument

Im trying to write to a TCP socket in Go but only receive "invalid argument" with this code:
_, err := conn.Write([]byte("test"))
if err != nil {
fmt.Println(err.Error())
}
Here is a simple sample of what you want to do(maybe?), be aware that you should make a tcp server listen to the port 8999 first before run it
nc -l 8999 #or maybe nc -l -p 8999
code:
package main
import (
"net"
)
func main() {
conn, _ := net.Dial("tcp", "localhost:8999")
conn.Write([]byte("test"))
}
If it's not your question, you should provide more information.

Trouble reading from a socket in go

I'm trying to learn the go language, and I'm writing a simple echo server. I'm having difficulty making it work, though.
func listen(server string) {
var buf []byte
listener, ok := net.Listen("tcp", server)
if ok != nil {
fmt.Fprintf(os.Stderr, "Could not listen on socket: %s\n", ok.String())
return
}
conn, ok := listener.Accept()
if ok != nil {
fmt.Fprintf(os.Stderr, "Could not accept connection on socket: %s\n", ok.String())
return
}
writelen, ok := conn.Write(strings.Bytes("Ready to receive\n"))
if ok != nil {
fmt.Fprintf(os.Stderr, "Could not write to socket: %s\n", ok.String())
} else {
fmt.Printf("Wrote %d bytes to socket\n", writelen)
}
for ;; {
readlen, ok := conn.Read(buf)
if ok != nil {
fmt.Fprintf(os.Stderr, "Error when reading from socket: %s\n", ok.String())
return
}
if readlen == 0 {
fmt.Printf("Connection closed by remote host\n")
return
}
fmt.Printf("Client at %s says '%s'\n", conn.RemoteAddr().String(), buf)
}
}
I get the following output from this function:
[nathan#ebisu ~/src/go/echo_server] ./6.out 1234
Using port 1234
Wrote 17 bytes to socket
Error when reading from socket: EOF
This is what I see on the client:
[nathan#ebisu ~] telnet 127.0.0.1 1234
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Ready to receive
Connection closed by foreign host.
Any help would be appreciated (or pointers to resources; the go documentation on the sockets API leaves a little to be desired).
Thanks,
Nathan
In your example, buf needs to have a definite size. You've declared it as a 0-length slice.
Declare it as:
var buf = make([]byte, 1024)
Of course, if you want to learn, it is better to write it yourself but, if it helps, here is my own echo server in Go.
package main
import (
"net";
"os";
"fmt";
)
func handle(conn *net.TCPConn) {
fmt.Printf("Connection from %s\n", conn.RemoteAddr());
message := make([]byte, 1024);
// TODO: loop the read, we can have >1024 bytes
n1, error := conn.Read(message);
if error != nil {
fmt.Printf("Cannot read: %s\n", error);
os.Exit(1);
}
n2, error := conn.Write(message[0:n1]);
if error != nil || n2 != n1 {
fmt.Printf("Cannot write: %s\n", error);
os.Exit(1);
}
fmt.Printf("Echoed %d bytes\n", n2);
conn.Close(); // TODO: wait to see if more data? It would be better with telnet...
}
func main() {
listen := ":7";
addr, error := net.ResolveTCPAddr(listen);
if error != nil {
fmt.Printf("Cannot parse \"%s\": %s\n", listen, error);
os.Exit(1);
}
listener, error := net.ListenTCP("tcp", addr);
if error != nil {
fmt.Printf("Cannot listen: %s\n", error);
os.Exit(1);
}
for { // ever...
conn, error := listener.AcceptTCP();
if error != nil {
fmt.Printf("Cannot accept: %s\n", error);
os.Exit(1);
}
go handle(conn);
}
}