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
It reads input from the user on the standard input stream, and then forwards that text to the echo server by writing the text to the socket. The server echoes the input back through the socket to the client. The client program reads and displays the data passed back to it from the server.
Behavior for sockets: The read() call reads data on a socket with descriptor fs and stores it in a buffer. The read() all applies only to connected sockets. This call returns up to N bytes of data. If there are fewer bytes available than requested, the call returns the number currently available.
Resolution. If you are getting a socket connect error when downloading the content filter database you may have a corrupt SSL client. The error message suggests that the process responsible for performing the download was unable to access the ssl-client data structure in memory.
One thread reading and one thread writing will work as you expect. Sockets are full duplex, so you can read while you write and vice-versa. You'd have to worry if you had multiple writers, but this is not the case.
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With