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
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
M$ cannot allow porting code from *nix without rewriting...
--
Steve
Michal
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!
<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
> 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
B-O
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
> 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
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!
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