2

I'm trying to use fprintf on a socket on Windows. Many of the online examples are UNIX examples. The equivalent code for Windows is what I'm asking about here.

Ultimately, I'd like to do this:

fprintf(file_handle_to_socket, "hello world\r\n");

I do not want to use WriteFile, snprintf or anything else. Just fprintf().

Pseudocode that more or less shows the steps would be helpful.

Here is what I have so far:

unsigned short port = enter_port;

int result = 0;
WSADATA wsaData;
result = WSAStartup(MAKEWORD(2, 2), &wsaData);

struct sockaddr_in local;
memset(&local, 0, sizeof(struct sockaddr_in));

local.sin_port = htons(port);
local.sin_family = AF_INET;
local.sin_addr.s_addr = htonl(INADDR_ANY);

int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == INVALID_SOCKET)
{
    fprintf(stdout,"invalid socket: error code %d\n", WSAGetLastError());
}

result = bind(sock, (struct sockaddr*)&local, sizeof(struct sockaddr_in));
if(result == SOCKET_ERROR)
{
    fprintf(stdout,"bind() failed: error code %d\n", WSAGetLastError());
}

result = listen(sock, 5);

struct sockaddr peer;
memset(&peer, 0, sizeof(struct sockaddr));

SOCKET client = 0;
int size = sizeof(struct sockaddr);
client = accept(sock, &peer, &size);

int OSFileHandle = _open_osfhandle(client, _O_APPEND);
FILE * file_handle_to_socket = fdopen(OSFileHandle, "w+");

fprintf(file_handle_to_socket, "Hello World\r\n");

// hoping this helps -- it doesn't
fflush(file_handle_to_socket);

fclose(file_handle_to_socket);
closesocket(client);

// this throws an exception
WSACleanup();

When I run this, nothing comes out on the other end (using putty) and I get an exception at WSACleanup(); The exception at WSACleanup is An invalid handle was specified.

UPDATE I found a strong lead by reading this post more closely. If I replace:

fprintf(file_handle_to_socket, "Hello World\r\n");

with

fprintfsock(client, "Hello World\r\n");

It works.

It's still not a complete answer to my question though. I'm looking to use fprintf() directly.

Community
  • 1
  • 1
101010
  • 14,866
  • 30
  • 95
  • 172

2 Answers2

4

A socket is not a file handle, so you cannot use _open_osfhandle() to wrap it. That is why fprintf() is not working. fprintfsock() is specifically designed to work with a socket directly. It is merely a wrapper that formats the data into a local buffer and then uses the socket API send() function to send it. If you really want to use fprintf() with a socket, you will have to #undef fprintf and then #define fprintf() to re-map it to fprintfsock() (which will only work if you are using a compiler that supports variadic macros). Otherwise, just use fprintfsock() directly.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • How does one declare and fill in his own FILE struct that uses his own callbacks to call send() and recv() internally? Is there not a function call that does this? Like fdopen()? – 101010 Jan 15 '13 at 19:05
  • 1
    No, there is no function that will set up a `FILE` struct using custom callbacks. In fact, now that I think about it, this won't work anyway because `fprintf()` is going to internally call file I/O functions that expect the `FILE*` to ultimately map to a real file, which a socket is not. So you will likely not be able to use `fprintf()` with socket I/O at all. Just use `fprintfsock()` instead. – Remy Lebeau Jan 15 '13 at 19:28
0

I have got a similar concern with a client part fprintf on socket using mingw, you should try to create the socket in non overlapped mode :

int sock = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 0);
Community
  • 1
  • 1
mpromonet
  • 11,326
  • 43
  • 62
  • 91