Intro
In this time, I will try sending and receiving data using TCP.
Also, I will try watching the packets at that time using Wireshark.
Environments
- Go ver.1.21.0
- Wireshark ver.4.0.8
Sample projects
[Client] main.go
package main
import (
"fmt"
"log"
"net"
)
func main() {
var conn net.Conn
var err error
defer func() {
if conn != nil {
conn.Close()
}
}()
buf := make([]byte, 1024)
conn, err = net.Dial("tcp", ":5055")
if err != nil {
log.Panicln(err.Error())
}
data := []byte(fmt.Sprintln("Hello1"))
_, err = conn.Write(data)
if err != nil {
log.Panicln(err.Error())
}
leng, err := conn.Read(buf)
if err != nil {
log.Panicln(err.Error())
}
log.Println(string(buf[:leng]))
}
[Server] main.go
package main
import (
"fmt"
"log"
"net"
)
func main() {
socket, err := net.Listen("tcp", "localhost:5055")
if err != nil {
log.Fatal(err.Error())
}
defer socket.Close()
conn, err := socket.Accept()
if err != nil {
log.Fatal(err.Error())
}
defer conn.Close()
for {
buf := make([]byte, 1024)
length, err := conn.Read(buf)
if err != nil {
log.Fatal(err.Error())
}
result := ""
for i := 0; i < length; i++ {
result = fmt.Sprintf("%s %02X", result, buf[i])
}
log.Println(result)
log.Println(string(buf[:length]))
_, err = conn.Write([]byte(fmt.Sprintf("Received: %d", length)))
if err != nil {
log.Fatal(err.Error())
}
}
}
[Client] Result
2023/09/13 01:26:23 Received: 7
[Server] Results
2023/09/13 01:26:23 48 65 6C 6C 6F 31 0A
2023/09/13 01:26:23 Hello1
2023/09/13 01:26:24 EOF
exit status 1
Watching packets
I will try following the flow of the above processing from the packets captured with Wireshark.
Connecting
- First, establish a TCP connection using 3-way handshake. At that time, each application generates a Sequence Number and sends it to the other party with the SYN or ACK flags.
- After receiving the number, they add 1 to it and hold it as an Acknowledgment Number. The value is the number that the application expects to be sent as the next Sequence Number.
- Now, both have the same values.
Send text data
- The client sends text data(7 bytes) to the server.
- The server receives them and adds 7 to the last Acknowledgment Number and hold it as new one.
- Now, both have the same values.
How to get the received data length?
To get new Acknowledge Number, the receiver has to get the received data length.
But according to RFC9293, the TCP header doesn't have data length.
It only has TCP header length(== Data Offset).
According to RFC791, the IP header has total length and IP header length.
Total Length(47) - (IP header length(5 * 4) + TCP header length(5 * 4)) = 7(bytes)
Sending data repeatedly in a short period of time
When I try sending data repeatedly in a short period of time, all of the received data will be merged.
[Client] main.go
...
func main() {
var conn net.Conn
var err error
defer func() {
if conn != nil {
conn.Close()
}
}()
buf := make([]byte, 1024)
conn, err = net.Dial("tcp", ":5055")
if err != nil {
log.Panicln(err.Error())
}
data := []byte(fmt.Sprintln("Hello1"))
_, err = conn.Write(data)
if err != nil {
log.Panicln(err.Error())
}
// second
data = []byte(fmt.Sprintln("Hello2"))
_, err = conn.Write(data)
if err != nil {
log.Panicln(err.Error())
}
// Third
data = []byte(fmt.Sprintln("Hello3"))
_, err = conn.Write(data)
if err != nil {
log.Panicln(err.Error())
}
leng, err := conn.Read(buf)
if err != nil {
log.Panicln(err.Error())
}
log.Println(string(buf[:leng]))
}
[Client] Result
2023/09/13 01:26:23 Received: 21
[Server] Results
2023/09/14 02:01:25 48 65 6C 6C 6F 31 0A 48 65 6C 6C 6F 32 0A 48 65 6C 6C 6F 33 0A
2023/09/14 02:01:25 Hello1
Hello2
Hello3
2023/09/14 02:01:25 EOF
exit status 1
To avoid that, I can change the buffer size to 7, because all of the data have same length.
[Server] main.go
...
func main() {
...
defer conn.Close()
for {
buf := make([]byte, 7)
length, err := conn.Read(buf)
if err != nil {
log.Fatal(err.Error())
}
result := ""
for i := 0; i < length; i++ {
result = fmt.Sprintf("%s %02X", result, buf[i])
}
log.Println(result)
log.Println(string(buf[:length]))
_, err = conn.Write([]byte(fmt.Sprintf("Received: %d", length)))
if err != nil {
log.Fatal(err.Error())
}
}
}
[Client] Result
2023/09/13 01:26:23 Received: 7
[Server] Results
2023/09/14 02:10:50 48 65 6C 6C 6F 31 0A
2023/09/14 02:10:50 Hello1
2023/09/14 02:10:50 48 65 6C 6C 6F 32 0A
2023/09/14 02:10:50 Hello2
2023/09/14 02:10:50 48 65 6C 6C 6F 33 0A
2023/09/14 02:10:50 Hello3
2023/09/14 02:10:50 read tcp 127.0.0.1:5055->127.0.0.1:52505: wsarecv: An existing connection was forcibly closed by the remote host.
exit status 1
Top comments (0)