Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly close a socket opened with fdopen?

I have a socket sock:

int sock = socket(...);
connect(sock, ...);
 // or sock = accept(sock_listen, 0, 0);

And I opened it with fdopen twice, so that I can use the buffered reader and writer in stdio, such as fwrite, fread, fgets and fprintf.

FILE *f_recv = fdopen(sock, "wb");
FILE *f_send = fdopen(sock, "rb");

// some IO here.

close(sock);
fclose(f_recv);
fclose(f_send);

But as we know, if I fclose a file, a close will be called subsequently, and fclose will fail.

And if I use only close, the memory of struct FILE is leaked.

How do I close it properly?


UPDATE:

Use fdopen once with "r+" makes reading and writing share the same lock, but I except the sending and receiving to work individually.

like image 580
RnMss Avatar asked Dec 26 '22 20:12

RnMss


2 Answers

Use dup() to obtain a duplicate file descriptor for passing to fdopen(). When you call fclose() that will be closed but the underlying socket will remain open and can be closed with close():

FILE *f_recv = fdopen(dup(sock), "wb");
FILE *f_send = fdopen(dup(sock), "rb");

// some IO here.

fclose(f_recv);
fclose(f_send);
close(sock);

Edit: You can of course combine this with just using a single FILE object for both reading and writing.

like image 114
ThomasH Avatar answered Jan 05 '23 08:01

ThomasH


I think calling fdopen() twice is a mistake for the reasons you give.

Just open it once with fdopen(), passing the mode string "r+b" to make it read/write and binary.

like image 39
unwind Avatar answered Jan 05 '23 06:01

unwind