golang socket doesn't send all bytes before Write() method returns
up vote
-3
down vote
favorite
Today when I try to send 100M data to my server (a very simple TCP server also written in Golang), I found that the TCPConn.Write method returns 104857600 and nil error and then I close the socket. But my server only receives very little data. I think it is because Write method works in async mode, so although the method returns 104857600, only a little data is sent to the server. So I want to know whether there is a way to set the Write work in sync mode or how to detect whether all data is sent to the server from the socket.
The code is as follows:
server:
const ListenAddress = "192.168.0.128:8888"
func main() {
var l net.Listener
var err error
l, err = net.Listen("tcp", ListenAddress)
if err != nil {
fmt.Println("Error listening:", err)
os.Exit(1)
}
defer l.Close()
fmt.Println("listen on " + ListenAddress)
for {
conn, err := l.Accept()
if err != nil {
fmt.Println("Error accepting: ", err)
os.Exit(1)
}
//logs an incoming message
fmt.Printf("Received message %s -> %s n", conn.RemoteAddr(), conn.LocalAddr())
// Handle connections in a new goroutine.
go handleRequest(conn)
}
}
func handleRequest(conn net.Conn) {
defer conn.Close()
rcvLen := 0
rcvData := make(byte,20 * 1024 * 1024) // 20M
for {
l , err := conn.Read(rcvData)
if err != nil {
fmt.Printf("%v", err)
return
}
rcvLen += l
fmt.Printf("recv: %drn", rcvLen)
conn.Write(rcvData[:l])
}
}
Client:
conn, err := net.Dial("tcp", "192.168.0.128:8888")
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
defer conn.Close()
data := make(byte, 500 * 1024 * 1024)
len, err := conn.Write(data)
fmt.Println("send len: ", len)
The output of the client:
send len: 524288000
The output of the server:
listen on 192.168.0.128:8888
Received message 192.168.0.2:50561 -> 192.168.0.128:8888
recv: 166440
recv: 265720
EOF
I know if I can make the client wait for a while by SetLinger method, the data will be all sent to the server before the socket is closed. But I want to find a way to make the socket send all data before returns without calling SetLinger(). Thanks in advance. Please excuse my poor English.
sockets asynchronous go
|
show 5 more comments
up vote
-3
down vote
favorite
Today when I try to send 100M data to my server (a very simple TCP server also written in Golang), I found that the TCPConn.Write method returns 104857600 and nil error and then I close the socket. But my server only receives very little data. I think it is because Write method works in async mode, so although the method returns 104857600, only a little data is sent to the server. So I want to know whether there is a way to set the Write work in sync mode or how to detect whether all data is sent to the server from the socket.
The code is as follows:
server:
const ListenAddress = "192.168.0.128:8888"
func main() {
var l net.Listener
var err error
l, err = net.Listen("tcp", ListenAddress)
if err != nil {
fmt.Println("Error listening:", err)
os.Exit(1)
}
defer l.Close()
fmt.Println("listen on " + ListenAddress)
for {
conn, err := l.Accept()
if err != nil {
fmt.Println("Error accepting: ", err)
os.Exit(1)
}
//logs an incoming message
fmt.Printf("Received message %s -> %s n", conn.RemoteAddr(), conn.LocalAddr())
// Handle connections in a new goroutine.
go handleRequest(conn)
}
}
func handleRequest(conn net.Conn) {
defer conn.Close()
rcvLen := 0
rcvData := make(byte,20 * 1024 * 1024) // 20M
for {
l , err := conn.Read(rcvData)
if err != nil {
fmt.Printf("%v", err)
return
}
rcvLen += l
fmt.Printf("recv: %drn", rcvLen)
conn.Write(rcvData[:l])
}
}
Client:
conn, err := net.Dial("tcp", "192.168.0.128:8888")
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
defer conn.Close()
data := make(byte, 500 * 1024 * 1024)
len, err := conn.Write(data)
fmt.Println("send len: ", len)
The output of the client:
send len: 524288000
The output of the server:
listen on 192.168.0.128:8888
Received message 192.168.0.2:50561 -> 192.168.0.128:8888
recv: 166440
recv: 265720
EOF
I know if I can make the client wait for a while by SetLinger method, the data will be all sent to the server before the socket is closed. But I want to find a way to make the socket send all data before returns without calling SetLinger(). Thanks in advance. Please excuse my poor English.
sockets asynchronous go
2
Writes are not asynchronous. What makes you think that your "server only receives very little data"? It doesn't matter how simple you think your code is, it can still be incorrect. Do include it in the question.
– Peter
Nov 11 at 12:42
2
"detect whether all data is sent to the server from the socket." - Do you really want to know if all data are sent (and might be still in transit and might get lost there) or do you rather want to know if all data got received and probably also processed by the server? My guess is the last in which case you need the server to send some kind of acknowledgement back.
– Steffen Ullrich
Nov 11 at 14:42
Maybe related github.com/golang/go/issues/25722
– alex
Nov 12 at 2:03
@Peter I add my code. Please have a look. I remain confused about the problem. Thanks.
– MartinZ
Nov 12 at 13:24
@SteffenUllrich I just want to ensure all the data is sent before Write() returns.
– MartinZ
Nov 12 at 13:26
|
show 5 more comments
up vote
-3
down vote
favorite
up vote
-3
down vote
favorite
Today when I try to send 100M data to my server (a very simple TCP server also written in Golang), I found that the TCPConn.Write method returns 104857600 and nil error and then I close the socket. But my server only receives very little data. I think it is because Write method works in async mode, so although the method returns 104857600, only a little data is sent to the server. So I want to know whether there is a way to set the Write work in sync mode or how to detect whether all data is sent to the server from the socket.
The code is as follows:
server:
const ListenAddress = "192.168.0.128:8888"
func main() {
var l net.Listener
var err error
l, err = net.Listen("tcp", ListenAddress)
if err != nil {
fmt.Println("Error listening:", err)
os.Exit(1)
}
defer l.Close()
fmt.Println("listen on " + ListenAddress)
for {
conn, err := l.Accept()
if err != nil {
fmt.Println("Error accepting: ", err)
os.Exit(1)
}
//logs an incoming message
fmt.Printf("Received message %s -> %s n", conn.RemoteAddr(), conn.LocalAddr())
// Handle connections in a new goroutine.
go handleRequest(conn)
}
}
func handleRequest(conn net.Conn) {
defer conn.Close()
rcvLen := 0
rcvData := make(byte,20 * 1024 * 1024) // 20M
for {
l , err := conn.Read(rcvData)
if err != nil {
fmt.Printf("%v", err)
return
}
rcvLen += l
fmt.Printf("recv: %drn", rcvLen)
conn.Write(rcvData[:l])
}
}
Client:
conn, err := net.Dial("tcp", "192.168.0.128:8888")
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
defer conn.Close()
data := make(byte, 500 * 1024 * 1024)
len, err := conn.Write(data)
fmt.Println("send len: ", len)
The output of the client:
send len: 524288000
The output of the server:
listen on 192.168.0.128:8888
Received message 192.168.0.2:50561 -> 192.168.0.128:8888
recv: 166440
recv: 265720
EOF
I know if I can make the client wait for a while by SetLinger method, the data will be all sent to the server before the socket is closed. But I want to find a way to make the socket send all data before returns without calling SetLinger(). Thanks in advance. Please excuse my poor English.
sockets asynchronous go
Today when I try to send 100M data to my server (a very simple TCP server also written in Golang), I found that the TCPConn.Write method returns 104857600 and nil error and then I close the socket. But my server only receives very little data. I think it is because Write method works in async mode, so although the method returns 104857600, only a little data is sent to the server. So I want to know whether there is a way to set the Write work in sync mode or how to detect whether all data is sent to the server from the socket.
The code is as follows:
server:
const ListenAddress = "192.168.0.128:8888"
func main() {
var l net.Listener
var err error
l, err = net.Listen("tcp", ListenAddress)
if err != nil {
fmt.Println("Error listening:", err)
os.Exit(1)
}
defer l.Close()
fmt.Println("listen on " + ListenAddress)
for {
conn, err := l.Accept()
if err != nil {
fmt.Println("Error accepting: ", err)
os.Exit(1)
}
//logs an incoming message
fmt.Printf("Received message %s -> %s n", conn.RemoteAddr(), conn.LocalAddr())
// Handle connections in a new goroutine.
go handleRequest(conn)
}
}
func handleRequest(conn net.Conn) {
defer conn.Close()
rcvLen := 0
rcvData := make(byte,20 * 1024 * 1024) // 20M
for {
l , err := conn.Read(rcvData)
if err != nil {
fmt.Printf("%v", err)
return
}
rcvLen += l
fmt.Printf("recv: %drn", rcvLen)
conn.Write(rcvData[:l])
}
}
Client:
conn, err := net.Dial("tcp", "192.168.0.128:8888")
if err != nil {
fmt.Println(err)
os.Exit(-1)
}
defer conn.Close()
data := make(byte, 500 * 1024 * 1024)
len, err := conn.Write(data)
fmt.Println("send len: ", len)
The output of the client:
send len: 524288000
The output of the server:
listen on 192.168.0.128:8888
Received message 192.168.0.2:50561 -> 192.168.0.128:8888
recv: 166440
recv: 265720
EOF
I know if I can make the client wait for a while by SetLinger method, the data will be all sent to the server before the socket is closed. But I want to find a way to make the socket send all data before returns without calling SetLinger(). Thanks in advance. Please excuse my poor English.
sockets asynchronous go
sockets asynchronous go
edited Nov 12 at 13:34
asked Nov 11 at 12:34
MartinZ
12
12
2
Writes are not asynchronous. What makes you think that your "server only receives very little data"? It doesn't matter how simple you think your code is, it can still be incorrect. Do include it in the question.
– Peter
Nov 11 at 12:42
2
"detect whether all data is sent to the server from the socket." - Do you really want to know if all data are sent (and might be still in transit and might get lost there) or do you rather want to know if all data got received and probably also processed by the server? My guess is the last in which case you need the server to send some kind of acknowledgement back.
– Steffen Ullrich
Nov 11 at 14:42
Maybe related github.com/golang/go/issues/25722
– alex
Nov 12 at 2:03
@Peter I add my code. Please have a look. I remain confused about the problem. Thanks.
– MartinZ
Nov 12 at 13:24
@SteffenUllrich I just want to ensure all the data is sent before Write() returns.
– MartinZ
Nov 12 at 13:26
|
show 5 more comments
2
Writes are not asynchronous. What makes you think that your "server only receives very little data"? It doesn't matter how simple you think your code is, it can still be incorrect. Do include it in the question.
– Peter
Nov 11 at 12:42
2
"detect whether all data is sent to the server from the socket." - Do you really want to know if all data are sent (and might be still in transit and might get lost there) or do you rather want to know if all data got received and probably also processed by the server? My guess is the last in which case you need the server to send some kind of acknowledgement back.
– Steffen Ullrich
Nov 11 at 14:42
Maybe related github.com/golang/go/issues/25722
– alex
Nov 12 at 2:03
@Peter I add my code. Please have a look. I remain confused about the problem. Thanks.
– MartinZ
Nov 12 at 13:24
@SteffenUllrich I just want to ensure all the data is sent before Write() returns.
– MartinZ
Nov 12 at 13:26
2
2
Writes are not asynchronous. What makes you think that your "server only receives very little data"? It doesn't matter how simple you think your code is, it can still be incorrect. Do include it in the question.
– Peter
Nov 11 at 12:42
Writes are not asynchronous. What makes you think that your "server only receives very little data"? It doesn't matter how simple you think your code is, it can still be incorrect. Do include it in the question.
– Peter
Nov 11 at 12:42
2
2
"detect whether all data is sent to the server from the socket." - Do you really want to know if all data are sent (and might be still in transit and might get lost there) or do you rather want to know if all data got received and probably also processed by the server? My guess is the last in which case you need the server to send some kind of acknowledgement back.
– Steffen Ullrich
Nov 11 at 14:42
"detect whether all data is sent to the server from the socket." - Do you really want to know if all data are sent (and might be still in transit and might get lost there) or do you rather want to know if all data got received and probably also processed by the server? My guess is the last in which case you need the server to send some kind of acknowledgement back.
– Steffen Ullrich
Nov 11 at 14:42
Maybe related github.com/golang/go/issues/25722
– alex
Nov 12 at 2:03
Maybe related github.com/golang/go/issues/25722
– alex
Nov 12 at 2:03
@Peter I add my code. Please have a look. I remain confused about the problem. Thanks.
– MartinZ
Nov 12 at 13:24
@Peter I add my code. Please have a look. I remain confused about the problem. Thanks.
– MartinZ
Nov 12 at 13:24
@SteffenUllrich I just want to ensure all the data is sent before Write() returns.
– MartinZ
Nov 12 at 13:26
@SteffenUllrich I just want to ensure all the data is sent before Write() returns.
– MartinZ
Nov 12 at 13:26
|
show 5 more comments
2 Answers
2
active
oldest
votes
up vote
2
down vote
Did you poll the socket before trying to write?
Behind the socket is your operating system's tcp stack. When writing on a socket, you push bytes to the send buffer. Your operating system then self determines when and how to send. If the receiving end has no buffer space.available in their receice buffer, your sending end knows this and will not put any more information in the send buffer.
Make sure your send buffer has enough space for whatever you are trying to send next. This is done by polling the socket. This method is usually called Socket.Poll. I.recommend you ccheck the golang docs for the exact usage.
add a comment |
up vote
1
down vote
You are not handling the error returned by conn.Read correctly. From the docs (emphasis mine):
When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-nil) error from the same call or return the error (and n == 0) from a subsequent call. [...]
Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed EOF behaviors.
Note that you are re-inventing io.Copy (albeit with an excessive buffer size). Your server code can be rewritten as:
func handleRequest(conn net.Conn) {
defer conn.Close()
n, err := io.Copy(conn, conn)
}
Thanks. After some days of study, I realize that Golang makes the TCPConn.Write works asynchronously, what I should do is give it time to send all data to the server internally. As for ensuring all data is sent successfully, the higher level protocols can ensure it.
– MartinZ
Nov 14 at 11:39
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
Did you poll the socket before trying to write?
Behind the socket is your operating system's tcp stack. When writing on a socket, you push bytes to the send buffer. Your operating system then self determines when and how to send. If the receiving end has no buffer space.available in their receice buffer, your sending end knows this and will not put any more information in the send buffer.
Make sure your send buffer has enough space for whatever you are trying to send next. This is done by polling the socket. This method is usually called Socket.Poll. I.recommend you ccheck the golang docs for the exact usage.
add a comment |
up vote
2
down vote
Did you poll the socket before trying to write?
Behind the socket is your operating system's tcp stack. When writing on a socket, you push bytes to the send buffer. Your operating system then self determines when and how to send. If the receiving end has no buffer space.available in their receice buffer, your sending end knows this and will not put any more information in the send buffer.
Make sure your send buffer has enough space for whatever you are trying to send next. This is done by polling the socket. This method is usually called Socket.Poll. I.recommend you ccheck the golang docs for the exact usage.
add a comment |
up vote
2
down vote
up vote
2
down vote
Did you poll the socket before trying to write?
Behind the socket is your operating system's tcp stack. When writing on a socket, you push bytes to the send buffer. Your operating system then self determines when and how to send. If the receiving end has no buffer space.available in their receice buffer, your sending end knows this and will not put any more information in the send buffer.
Make sure your send buffer has enough space for whatever you are trying to send next. This is done by polling the socket. This method is usually called Socket.Poll. I.recommend you ccheck the golang docs for the exact usage.
Did you poll the socket before trying to write?
Behind the socket is your operating system's tcp stack. When writing on a socket, you push bytes to the send buffer. Your operating system then self determines when and how to send. If the receiving end has no buffer space.available in their receice buffer, your sending end knows this and will not put any more information in the send buffer.
Make sure your send buffer has enough space for whatever you are trying to send next. This is done by polling the socket. This method is usually called Socket.Poll. I.recommend you ccheck the golang docs for the exact usage.
answered Nov 11 at 12:52
Dennis19901
533
533
add a comment |
add a comment |
up vote
1
down vote
You are not handling the error returned by conn.Read correctly. From the docs (emphasis mine):
When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-nil) error from the same call or return the error (and n == 0) from a subsequent call. [...]
Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed EOF behaviors.
Note that you are re-inventing io.Copy (albeit with an excessive buffer size). Your server code can be rewritten as:
func handleRequest(conn net.Conn) {
defer conn.Close()
n, err := io.Copy(conn, conn)
}
Thanks. After some days of study, I realize that Golang makes the TCPConn.Write works asynchronously, what I should do is give it time to send all data to the server internally. As for ensuring all data is sent successfully, the higher level protocols can ensure it.
– MartinZ
Nov 14 at 11:39
add a comment |
up vote
1
down vote
You are not handling the error returned by conn.Read correctly. From the docs (emphasis mine):
When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-nil) error from the same call or return the error (and n == 0) from a subsequent call. [...]
Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed EOF behaviors.
Note that you are re-inventing io.Copy (albeit with an excessive buffer size). Your server code can be rewritten as:
func handleRequest(conn net.Conn) {
defer conn.Close()
n, err := io.Copy(conn, conn)
}
Thanks. After some days of study, I realize that Golang makes the TCPConn.Write works asynchronously, what I should do is give it time to send all data to the server internally. As for ensuring all data is sent successfully, the higher level protocols can ensure it.
– MartinZ
Nov 14 at 11:39
add a comment |
up vote
1
down vote
up vote
1
down vote
You are not handling the error returned by conn.Read correctly. From the docs (emphasis mine):
When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-nil) error from the same call or return the error (and n == 0) from a subsequent call. [...]
Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed EOF behaviors.
Note that you are re-inventing io.Copy (albeit with an excessive buffer size). Your server code can be rewritten as:
func handleRequest(conn net.Conn) {
defer conn.Close()
n, err := io.Copy(conn, conn)
}
You are not handling the error returned by conn.Read correctly. From the docs (emphasis mine):
When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-nil) error from the same call or return the error (and n == 0) from a subsequent call. [...]
Callers should always process the n > 0 bytes returned before considering the error err. Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed EOF behaviors.
Note that you are re-inventing io.Copy (albeit with an excessive buffer size). Your server code can be rewritten as:
func handleRequest(conn net.Conn) {
defer conn.Close()
n, err := io.Copy(conn, conn)
}
answered Nov 12 at 14:03
Peter
15.1k42032
15.1k42032
Thanks. After some days of study, I realize that Golang makes the TCPConn.Write works asynchronously, what I should do is give it time to send all data to the server internally. As for ensuring all data is sent successfully, the higher level protocols can ensure it.
– MartinZ
Nov 14 at 11:39
add a comment |
Thanks. After some days of study, I realize that Golang makes the TCPConn.Write works asynchronously, what I should do is give it time to send all data to the server internally. As for ensuring all data is sent successfully, the higher level protocols can ensure it.
– MartinZ
Nov 14 at 11:39
Thanks. After some days of study, I realize that Golang makes the TCPConn.Write works asynchronously, what I should do is give it time to send all data to the server internally. As for ensuring all data is sent successfully, the higher level protocols can ensure it.
– MartinZ
Nov 14 at 11:39
Thanks. After some days of study, I realize that Golang makes the TCPConn.Write works asynchronously, what I should do is give it time to send all data to the server internally. As for ensuring all data is sent successfully, the higher level protocols can ensure it.
– MartinZ
Nov 14 at 11:39
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53248807%2fgolang-socket-doesnt-send-all-bytes-before-write-method-returns%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
Writes are not asynchronous. What makes you think that your "server only receives very little data"? It doesn't matter how simple you think your code is, it can still be incorrect. Do include it in the question.
– Peter
Nov 11 at 12:42
2
"detect whether all data is sent to the server from the socket." - Do you really want to know if all data are sent (and might be still in transit and might get lost there) or do you rather want to know if all data got received and probably also processed by the server? My guess is the last in which case you need the server to send some kind of acknowledgement back.
– Steffen Ullrich
Nov 11 at 14:42
Maybe related github.com/golang/go/issues/25722
– alex
Nov 12 at 2:03
@Peter I add my code. Please have a look. I remain confused about the problem. Thanks.
– MartinZ
Nov 12 at 13:24
@SteffenUllrich I just want to ensure all the data is sent before Write() returns.
– MartinZ
Nov 12 at 13:26