Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

fdopen and socket problem

701 views
Skip to first unread message

Silvio

unread,
Sep 26, 2007, 10:41:59 AM9/26/07
to
Hi!
I have a "Permision denied" error when I try open file descriptor from a
socket.
This error appears in ruby-1.8.6 compiling.

I paste a simple code with gives the error .........................

/* A simple server in the internet domain using TCP
The port number is passed as an argument */
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <sys/types.h>
#include <windows.h>
#include <winsock2.h>

void error(char *msg)
{
perror(msg);
system( "pause" );
exit(1);
}

int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
FILE* file;

WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 2, 0 );

err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
/* Tell the user that we couldn't find a usable */
/* WinSock DLL. */
return 0;
}


sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
memset((char *) &serv_addr, 0, sizeof(serv_addr));
portno = 8080;

serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);

if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");

listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0)
error("ERROR on accept");
memset(buffer,0,256);

file = fdopen( newsockfd, "rw" );
if( !file ) error( "FDOPEN" ); // HERE!!!!!

n = recv(newsockfd, buffer, 255, 0 );
printf( "file= %d n= %d\n", file, n );

if (n < 0) error("ERROR reading from socket");
printf("Here is the message: %s\n",buffer);
n = send(newsockfd,"I got your message",18, 0);
if (n < 0) error("ERROR writing to socket");

system( "pause" );
return 0;
}


...............
When I execute this little program and, from another console I call
"telnet localhost 8080" the Permission Denied Error appears.
Somebody can help me?

Thanks,
Silvio

Berth-Olof Bergman

unread,
Sep 26, 2007, 11:38:15 AM9/26/07
to
Silvio wrote:
> newsockfd = accept(sockfd,
> (struct sockaddr *) &cli_addr,
> &clilen);
> if (newsockfd < 0)
> error("ERROR on accept");
> memset(buffer,0,256);
>
> file = fdopen( newsockfd, "rw" );
> if( !file ) error( "FDOPEN" ); // HERE!!!!!
>
> When I execute this little program and, from another console I call
> "telnet localhost 8080" the Permission Denied Error appears.
> Somebody can help me?
>

Socket handles are not file descriptors in Windows as they are in Unix.
Socket handles in Windows are not compatible with fdopen and stdio.

B-O


Steve Fabian

unread,
Sep 26, 2007, 12:01:51 PM9/26/07
to
Berth-Olof Bergman wrote:
| Socket handles are not file descriptors in Windows as they are in
| Unix. Socket handles in Windows are not compatible with fdopen and
| stdio.

M$ cannot allow porting code from *nix without rewriting...
--
Steve


Michal Necasek

unread,
Sep 26, 2007, 1:38:58 PM9/26/07
to

I don't think what you're trying to do is possible (on Win32). You can
try ReadFile on the socket handle - if it doesn't work (in my
experiment, it didn't), fread() definitely won't. If ReadFile did work,
you'd still need _open_osfhandle() or something along those lines to
convert the handle you got from the OS into one you could use for fdopen().


Michal

Silvio

unread,
Sep 26, 2007, 6:07:10 PM9/26/07
to
Michal Necasek escribió:

With mingw32 I have not problems using _open_osfhandle() (and I suppose
VisualC too), but Open Watcom remains in permission error.
In fact, I recompiled all ruby with mingw32 and they works fine.


/*
---------------------------------------------------------------------------------
The new program, using _open_osfhandle. Works fine in mingw32
---------------------------------------------------------------------------------


A simple server in the internet domain using TCP
The port number is passed as an argument */

#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <sys/types.h>
#include <windows.h>
#include <winsock2.h>

void error(char *msg)
{
perror(msg);
system( "pause" );
exit(1);
}

int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;

int osfh;
FILE* file;

osfh = _open_osfhandle((SOCKET)newsockfd, O_RDWR|O_BINARY);
if( osfh < 0 ) error( "ERROR on _open_osfhandle" );

file = fdopen( osfh, "rw" );
if( !file ) error( "ERROR on FDOPEN" );

n = recv(newsockfd,buffer, 255, 0 );
if( n < 0 ) error("ERROR reading from socket");
printf( buffer );

n = send(newsockfd ,"I got your message\n", 18, 0);

if (n < 0) error("ERROR writing to socket");

return 0;
}

---------------------------------------------------------------------------------
End of the new program!
---------------------------------------------------------------------------------


Silvio
PD: Sorry by my english!

Mat Nieuwenhoven

unread,
Sep 27, 2007, 12:14:01 AM9/27/07
to
On Wed, 26 Sep 2007 11:41:59 -0300, Silvio wrote:

<snip>


> clilen = sizeof(cli_addr);
> newsockfd = accept(sockfd,
> (struct sockaddr *) &cli_addr,
> &clilen);
> if (newsockfd < 0)
> error("ERROR on accept");
> memset(buffer,0,256);
>
> file = fdopen( newsockfd, "rw" );
> if( !file ) error( "FDOPEN" ); // HERE!!!!!
>
> n = recv(newsockfd, buffer, 255, 0 );
> printf( "file= %d n= %d\n", file, n );

You don't need the fdopen after the accept for recv to work. But you cannot
use the same file descriptor for a printf and a socket operation. If your
printf is supposed to send something to the socket, use send instead.

Mat Nieuwenhoven


Roman Trunov

unread,
Sep 27, 2007, 3:20:52 AM9/27/07
to
Silvio wrote:

> With mingw32 I have not problems using _open_osfhandle()

Yes (see below).

> (and I suppose VisualC too),

No, it'll give you same error as in Watcom.

In Unix world, sockets and file handles are interchangeable. You can use
read() and write() on sockets and select() on files. In Windows and
OS/2, they're not. This is a principal ideological difference between
these types of systems - Windows or OS/2 can exist without TCP/IP
support (this is a just an installable networking protocol, one of
many), Unix can not.

In mingw32 and other gcc-based systems, this difference is handled by
specially designed runtime library. It's tracking type of the every
handle (file or socket) and calls necessary system I/O functions - e.g.
ReadFile() or recv(), CloseFile() or closesocket(). Watcom or VisualC
runtimes do not have this extra emulation layer.

I other words, if you want to quickly compile some poorly-writen
unix-centric badly portable code, use mingw or other gcc-based stuff.
Watcom/MSVC will give better results and more efficient faster/smaller
applications, but you have to do lot of porting and fixing of original
source to remove all unix'isms.

Roman

Berth-Olof Bergman

unread,
Sep 27, 2007, 3:54:04 AM9/27/07
to
Roman Trunov wrote:
>
> I other words, if you want to quickly compile some poorly-writen
> unix-centric badly portable code, use mingw or other gcc-based stuff.
> Watcom/MSVC will give better results and more efficient faster/smaller
> applications, but you have to do lot of porting and fixing of original
> source to remove all unix'isms.
>
Well spoken!!!

B-O


Bart Oldeman

unread,
Sep 27, 2007, 7:48:43 AM9/27/07
to
On 2007-09-27, Roman Trunov <pro...@tula.net> wrote:
> Silvio wrote:
>
>> With mingw32 I have not problems using _open_osfhandle()
>
> Yes (see below).
>
>> (and I suppose VisualC too),
>
> No, it'll give you same error as in Watcom.

Hmm, I'm surprised. AFAIK MinGW only provides a very thin wrapper
around MSVCRT, where the wrapper just adds a few functions such as
snprintf and strcasecmp, not doing anything extensive like you describe
below.

> In mingw32 and other gcc-based systems, this difference is handled by
> specially designed runtime library. It's tracking type of the every
> handle (file or socket) and calls necessary system I/O functions - e.g.
> ReadFile() or recv(), CloseFile() or closesocket(). Watcom or VisualC
> runtimes do not have this extra emulation layer.

I certainly believe you for Cygwin though.

Bart

Michal Necasek

unread,
Sep 27, 2007, 8:20:12 AM9/27/07
to
Bart Oldeman wrote:

> On 2007-09-27, Roman Trunov <pro...@tula.net> wrote:
>> Silvio wrote:
>>
>>> With mingw32 I have not problems using _open_osfhandle()
>> Yes (see below).
>>
>>> (and I suppose VisualC too),
>> No, it'll give you same error as in Watcom.
>
> Hmm, I'm surprised. AFAIK MinGW only provides a very thin wrapper
> around MSVCRT, where the wrapper just adds a few functions such as
> snprintf and strcasecmp, not doing anything extensive like you describe
> below.
>

I think the OP is spreading confusion. In my tests, fdopen() will
succeed (with OW or MSVC or DMC) as long as _open_osfhandle() is used,
which is standard procedure (on Win32) for any handle coming from the OS.

However, read() or fread() from the socket will fail, and so will
ReadFile.

Although remarkably poorly documented, the handle returned by accept()
is supposed to be usable with ReadFile(Ex), *but* apparently only for
overlapped I/O.

I too would be very surprised if read()/fread() worked on the socket
in MinGW.


Michal

Silvio

unread,
Sep 27, 2007, 12:41:51 PM9/27/07
to
Friends:
I am been thankful to all by its commentaries.
The problem was resolved opening file handle and file descriptor like
binary ....

osfh = _open_osfhandle((SOCKET)newsockfd, O_RDWR|O_BINARY);
if( osfh < 0 ) error( "ERROR on _open_osfhandle" );

file = fdopen( osfh, "rwb" );


if( !file ) error( "ERROR on FDOPEN" );

I had solved this in the ruby function connect(), but in a stroke of luck!

Roman:
Write to Yukihiro “matz” Matsumoto (Ruby creator) your words. Yes, the
great language is Unix centric, but works with MSVC and not with Watcom ;)

I ported and tested another Unix centric open source with Watcom
(DBBerkeley, gettext, fltk, iconv) and got good result.

Navigating in the ruby code I saw that the problem is solved using an
external variable __pioinfo (that not exists in Watcom) and a "native
_open_osfhandle" function.

I tested the resulted exe with Open Watcom and it is 20% more faster
than MSVC distributed version, without using optimizations. There are
small errors but I could be solved (like accept).

The work is published in http://rubyforge.org/projects/ruby-ow-patches/.
This night I will update the last patch.

Thanks!
Silvio
PD: Once again! Sorry by my poor english!

Silvio

unread,
Sep 28, 2007, 12:49:52 PM9/28/07
to
Roman Trunov escribió:

> Silvio wrote:
>
>> The problem was resolved opening file handle and file descriptor like
>> binary ....
>
> Ah, I think I'm remembering now. I got exactly same error few weeks ago.
> File open modes must match between of original handle obtained by
> (open() or _open_osfhandle()):

>
>> osfh = _open_osfhandle((SOCKET)newsockfd, O_RDWR|O_BINARY);
>> file = fdopen( osfh, "rwb" );
>
> I also got "access denied" error when original handle was opened in text
> mode and tried to fdopen() it in binary.
>
> You won't believe, but this requirement is even documented in fdopen()
> help page :)

Sorry! I don't find the requirement. I searched in .hlp file and google
before to write to list.

>
> Also it look like we have two separate problems here. The first one was
> mismatched open modes, it was solved. Fun is in following: all that
> stuff (fopen etc.) wasn't required at all in your testcase! A variable
> 'file' was never used!. All REAL work was done by true TCP/IP functions:
> recv() and send() So why your test worked. Just kill fdopen, it's not
> required.

It's true, but the Ruby code makes it :(
The IO object call after socket recv and send functions .

Without too much deep, I believe they uses the file descriptor for
obtain another information in Unix and persistently switch from socket
to file descriptor and vice versa.
I understand that fprintf dont work later, but was very cheap to make
work fdopen than modify entire logic of the ruby IO object.

>
> Roman

much obliged!
Silvio

0 new messages