Struct and Thread DWORD WINAPI - sockets

What's up guys, hope you are ok !
well, the problem is that I'm doing a chat client/server aplication but doing some tests with the server, I found out that I have a problem sending messages. I'm using a struct, sockets and DWORD WINAPI threads...
So the code in the struct is:
DWORD WINAPI threadSendMessages(LPVOID vpParam); //THREAD
typedef struct messagesServerChat{ //STRUCT
const char *messageServEnv;
}MESSAGE, *SMESSAGES;
then in the main method I call the struct to use the const char messageServEnv, a HeapAlloc to give some memory to the thread that is going to send the message and a char variable that I use to store the message
char mServer[1024] = ""; //variable to pre-store the message
SMESSAGES messages; //call the struct
messages = (SMESSAGES) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MESSAGE));
in the main method, I ask the user to insert the message that he wants to send and I use the struct to store the message and send it to the thread as a parameter:
cout<<"Dear user, please insert your message: ";
setbuf(stdin, NULL);
fgets(mServer, 1024, stdin);
messages->messageServEnv = mServer;
DWORD hSend; //send the parameters to the thread function
HANDLE sendThread = CreateThread(0, 0, threadSendMessages, mServer, 0, &hSend);
and finally the thread code function
DWORD WINAPI threadSendMessages(LPVOID lpParam){
SMESSAGES messages;
messages = (SMESSAGES)lpParam;
int mesa;
mesa = send(sConnect, (char *)messages->messageServEnv, sizeof messages->messageServEnv, 0);
//sConnect is the socket
//messages = to use the struct, and messageServEnv is the struct data that should contain the message
return 0;
}
--Edit-- I fix a lot of problems using Remy's solution but maybe I'm missing something... in the Thread threadSendMessages(SMESSAGES lpMessage)
char *ptr = messages->messageServEnv;
int len = strlen(messages->messageServEnv);
I get and error that says messages is undifined, then, I changed to:
SMESSAGES messages;
char *ptr = messages->messageServEnv;
int len = strlen(messages->messageServEnv);
now I can use messages and struct value messageServEnv but if I start debugging visual studio and I try to send a message, I get an error that says messages is used without being initialized, then I change that part to
SMESSAGES messages = new MESSAGE;
and now I can send messages to client but only characters and garbage code

You need to dynamically allocate the memory for each message's string data and then have the thread free the memory when finished sending it.
You are also passing the wrong pointer to the lpParameter parameter of CreateThread(), you are passing your char[] buffer instead of your allocated MESSAGE struct.
You are also using sizeof() when calling send(). Since your messageServEnv is a char* pointer, sizeof() will return 4 (32-bit) or 8 (64-bit) instead of the actual size of the string that is being pointed at.
I would suggest moving the char[] buffer directly into the struct instead of using a pointer to an external buffer, eg:
typedef struct messagesServerChat
{
char messageServEnv[1024];
}
MESSAGE, *SMESSAGES;
DWORD WINAPI threadSendMessages(SMESSAGES lpMessage);
.
cout << "Dear user, please insert your message: ";
setbuf(stdin, NULL);
SMESSAGES message = new MESSAGE;
fgets(message->messageServEnv, sizeof(message->messageServEnv), stdin);
DWORD hSend;
HANDLE sendThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&threadSendMessages, message, 0, &hSend);
if (!sendThread)
delete message;
.
DWORD WINAPI threadSendMessages(SMESSAGES lpMessage)
{
// send() is not guaranteed to send the entire message
// in one go, so call it in a loop...
char *ptr = lpMessage->messageServEnv;
int len = strlen(lpMessage->messageServEnv); // or sizeof() if you really want to send all 1024 bytes instead
while (len > 0)
{
int mesa = send(sConnect, ptr, len, 0);
if (mesa > 0)
{
ptr += mesa;
len -= mesa;
continue;
}
// this is only needed if you are using a non-blocking socket...
if ((mesa == SOCKET_ERROR) && (WSAGetLastError() == WSAEWOULDBLOCK))
{
fd_set fd;
FD_ZERO(&fd);
FD_SET(sConnect, &fd);
timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
if (select(0, NULL, &fd, NULL, &tv) > 0)
continue;
}
... error handling ...
break;
}
delete message;
return 0;
}
If you want to pass a dynamically-lengthed string instead, you are better off using a std::string instead of a char[]:
typedef struct messagesServerChat
{
std::string messageServEnv;
}
MESSAGE, *SMESSAGES;
DWORD WINAPI threadSendMessages(SMESSAGES lpMessage);
.
cout << "Dear user, please insert your message: ";
setbuf(stdin, NULL);
SMESSAGES message = new MESSAGE;
getline(stdin, message->messageServEnv);
DWORD hSend;
HANDLE sendThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&threadSendMessages, message, 0, &hSend);
if (!sendThread)
delete message;
.
DWORD WINAPI threadSendMessages(SMESSAGES lpMessage)
{
// send() is not guaranteed to send the entire message
// in one go, so call it in a loop...
char *ptr = lpMessage->messageServEnv.c_str();
int len = lpMessage->messageServEnv.length(); // or sizeof() if you really want to send all 1024 bytes instead
while (len > 0)
{
int mesa = send(sConnect, ptr, len, 0);
if (mesa > 0)
{
ptr += mesa;
len -= mesa;
continue;
}
// this is only needed if you are using a non-blocking socket...
if ((mesa == SOCKET_ERROR) && (WSAGetLastError() == WSAEWOULDBLOCK))
{
fd_set fd;
FD_ZERO(&fd);
FD_SET(sConnect, &fd);
timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
if (select(0, NULL, &fd, NULL, &tv) > 0)
continue;
}
... error handling ...
break;
}
delete message;
return 0;
}

Related

I'm converting ints to chars and trying to send them from a C client to a Python server on another computer. Getting 'send: Bad address'

On one computer with the client (written in C) I get the error send: Bad address when I try to send chars to another computer with a server written in Python. But the address is NOT bad.
If instead of chars I just send a written string, "A string written like this" I can send it just fine to the server and see it print with no problems. So, I don't think there is really a problem with an address.
I have also tried converting the int to a string. I get error when compiling cannot convert string to char. I have tried variations and I can only compile with the client written as it is below.
The client (in C)
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#define ADDR "192.168.0.112"
#define PORT "12003"
void sendall(int socket, char *bytes, int length)
{
int n = 0, total = 0;
while (total < length) {
n = send(socket, bytes + total, total-length, 0);
if (n == -1) {
perror("send");
exit(1);
}
total += n;
}
}
void thesock(char *ADDRf, char *PORTf, char *RAZZstr)
{
struct addrinfo hints = {0}, *addr = NULL;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
int status = getaddrinfo(ADDRf, PORTf, &hints, &addr);
if (status != 0) {
std::cerr << "Error message";
exit(1);
}
int sock = -1;
struct addrinfo *p = NULL;
for (p = addr; p != NULL; p = addr->ai_next) {
sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (sock == -1) {
continue;
}
if (connect(sock, p->ai_addr, p->ai_addrlen) != -1) {
break;
}
close(sock);
}
if (p == NULL) {
fprintf(stderr, "connect(), socket()\n");
exit(1);
}
sendall(sock, RAZZstr, 12);
close(sock);
}
int main()
{
int someInt = 321;
char strss[12];
sprintf(strss, "%d", someInt);
thesock(ADDR, PORT, strss);
return 0;
}
This last part of the code above is where the chars, or string is entered. It's this part of the code where you can replace strss in thesock with a string written in the strss position "just like this" and it will send to the server on the other computer written in Python. Though, when compiling I do get warnings ISO C++ forbids converting a string constant to ‘char*’.
The server (In Python)
import os
import sys
import socket
s=socket.socket()
host='192.168.0.112'
port=12003
s.bind((host,port))
s.listen(11)
while True:
c, addr=s.accept()
content=c.recv(29).decode('utf-8')
print(content)
This server decodes utf-8. I don't know if I have the option for a different 'decode' here. I don't think Python has 'chars'.
TL;DR: this is unrelated to "address" in terms of IP address but it is about invalid access to a local memory access.
int n = 0, total = 0;
while (total < length) {
n = send(socket, bytes + total, total-length, 0);
total - length is a negative number, i.e. 0-12 = -12 in your case. The third argument of send is of type size_t, i.e. an unsigned integer. The negative number (-12) thus gets cast into an unsigned integer, resulting in a huge unsigned integer.
This causes send to access memory far outside the allocated memory for bytes, hence EFAULT "Bad address".

Where is wrong with my STUN Binding request

I send udp request to stun.l.google.com:19305, but I don't get any response from google stun server. I omit all of the error check in this piece of code. My program hang in recvfrom.
int stun_socket = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in stun_client;
memset(&stun_client, 0, sizeof(stun_client));
stun_client.sin_family = AF_INET;
stun_client.sin_port = htons(local_port);
int rc = bind(stun_socket, (struct sockaddr *)&stun_client, sizeof(stun_client));
struct sockaddr_in stun_server;
memset(&stun_server, 0, sizeof(stun_server));
stun_server.sin_family = AF_INET;
stun_server.sin_port = htons(remote_port);
inet_pton(AF_INET, server, &stun_server.sin_addr);
typedef struct stun_header_tag {
uint16_t message_type;
uint16_t message_length;
unsigned char transaction_id[16];
} stun_header_t;
stun_header_t header;
header.message_type = htons(0x0001); /* Binding Request */
header.message_length = htons(0);
*(int *)(&header.transaction_id[8]) = 0xFFEEFFEE; /* transaction id in the response should keep consistent with this one */
rc = sendto(stun_socket, (void *)&header, sizeof(header), 0, (struct sockaddr *)&stun_server, sizeof(stun_server));
char response[64];
rc = recvfrom(stun_socket, response, 64, 0, NULL, 0);
I'm guessing you are doing something similar to this or equivalent for sending the data:
sendto(sock, &header, sizeof(header), (sockaddr*)&addr, addrlen);
If that's the case, you likely forgot to convert your message_type value to network byte order (big-endian).
Try this:
header.message_type = htons(0x0001);
But if you want a better solution, and you can use C++, use the client library built into Stuntman. You can generate a binding request as follows with the C++ class, CStunMessageBuilder, declared in the stuncore/stunbuilder.h file.
CStunMessageBuilder builder;
StunTransactionId transId;
builder.AddBindingRequestHeader();
builder.AddRandomTransactionId(&transID);
unsigned char* msg = builder.GetStream().GetDataPointerUnsafe();
size_t len = builder.GetStream().GetSize();
sendto(sock, msg, len, (sockaddr*)&addr, addrlen);

sendto() returning -1 in server

int main()
{
int servsocket,clientsocket;
struct sockaddr_in server,client;
FILE *file;
char filename[100];
char buf[1024];
servsocket=socket(AF_INET,SOCK_DGRAM,0);
server.sin_addr.s_addr=htonl(INADDR_ANY);
server.sin_port=htons(6003);
server.sin_family=AF_INET;
bind(servsocket,(struct sockaddr *) &server,sizeof(server) );
while(1){
int clientsize=0;
printf("Waiting for file requests \n");
recvfrom(servsocket,filename,sizeof(filename),0,(struct sockaddr *)&client,&clientsize);
file=fopen(filename,"r");
int size=0;
do
{
size=fread(buf,1,sizeof(buf),file);
printf("%d bytes read \n",size);
int sentbytes= sendto(servsocket,(const char *)buf,size,0, (struct sockaddr *) &client,sizeof(client));
printf("%d bytes sent ",sentbytes);
}while(size==sizeof(buf));
}
}
I am trying to make a simple program for file transfer using UDP. The problem is that sendto() always returns -1. This is the code for server.
There are quite a few issues with your code. The one you're seeing is that you're not filling in the variable client properly: the clientsize parameter is used for both input and output by the recvfrom system call, so you need to initialise it to the size of the client structure:
int clientsize = sizeof(struct sockaddr_in);
Another issue is that you're not 0-terminating the filename string:
n = recvfrom(...);
filename[n] = '\0';
Finally, you're not testing for errors (bind, recvfrom, sendto, etc.). This will get you into trouble, I promise.

Dispatch source is only called when I do a NSLog() first

I am trying to use grand central dispatch in conjunction with bsd sockets to send an icmp ping. I add DISPATCH_SOURCE_TYPE_WRITE and DISPATCH_SOURCE_TYPE_READ as dispatch sources to read and write async.
So this is the method were I create the bsd socket and install the dispatch sources:
- (void)start
{
int err;
const struct sockaddr * addrPtr;
assert(self.hostAddress != nil);
// Open the socket.
addrPtr = (const struct sockaddr *) [self.hostAddress bytes];
fd = -1;
err = 0;
switch (addrPtr->sa_family) {
case AF_INET: {
fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
if (fd < 0) {
err = errno;
}
} break;
case AF_INET6:
assert(NO);
// fall through
default: {
err = EPROTONOSUPPORT;
} break;
}
if (err != 0) {
[self didFailWithError:[NSError errorWithDomain:NSPOSIXErrorDomain code:err userInfo:nil]];
} else {
dispatch_source_t writeSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, fd, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
dispatch_source_set_event_handler(writeSource, ^{
abort(); // testing
// call call method here to send a ping
});
dispatch_resume(writeSource);
//NSLog(#"testout");
dispatch_source_t readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
dispatch_source_set_event_handler(readSource, ^{
unsigned long bytesAvail = dispatch_source_get_data(readSource);
NSLog(#"bytes available: %lu", bytesAvail);
});
dispatch_resume(readSource);
}
}
You see the //NSLog(#"testout");? The funny thing is that the write block is only called when the //NSLog(#"testout"); is NOT commented out. This is very odd. I didn't test the read callback. The sending needs to be working first.
So what is going on here?
There are kind of a bunch of things missing here. I'm not sure exactly which one is causing the weird behavior, but when I do all of the missing things, it seems to work "as expected" and my write event handler is called reliably and repeatedly. In general, there are a bunch of things you need to do when setting up a socket like this before passing it off to GCD. They are:
Create the socket
Bind it to a local address (missing in your code)
Set it to non-blocking (missing in your code)
Here is a little example I was able to put together in which the write handler gets called repeatedly, as expected:
int DoStuff()
{
int fd = -1;
// Create
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("cannot create socket");
return 0;
}
// Bind
struct sockaddr_in *localAddressPtr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
memset((char *)localAddressPtr, 0, sizeof(*localAddressPtr));
localAddressPtr->sin_family = AF_INET;
localAddressPtr->sin_addr.s_addr = htonl(INADDR_ANY);
localAddressPtr->sin_port = htons(0);
if (bind(fd, (struct sockaddr *)localAddressPtr, sizeof(*localAddressPtr)) < 0) {
perror("bind failed");
return 0;
}
// Set non-blocking
int flags;
if (-1 == (flags = fcntl(fd, F_GETFL, 0)))
flags = 0;
if (-1 == fcntl(fd, F_SETFL, flags | O_NONBLOCK))
{
perror("Couldnt set non-blocking");
return 0;
}
// Do a DNS lookup...
struct hostent *hp;
struct sockaddr_in *remoteAddressPtr = malloc(sizeof(struct sockaddr_in));
// Fill in the server's address and data
memset((char*)remoteAddressPtr, 0, sizeof(*remoteAddressPtr));
remoteAddressPtr->sin_family = AF_INET;
remoteAddressPtr->sin_port = htons(12345);
// Look up the address of the server by name
const char* host = "www.google.com";
hp = gethostbyname(host);
if (!hp) {
fprintf(stderr, "could not obtain address of %s\n", host);
return 0;
}
// Copy the host's address into the remote address structure
memcpy((void *)&remoteAddressPtr->sin_addr, hp->h_addr_list[0], hp->h_length);
dispatch_source_t writeSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, fd, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
dispatch_source_set_event_handler(writeSource, ^{
// Send message
const char* my_message = "the only thing we have to fear is fear itself.";
unsigned long len = strlen(my_message);
if (sendto(fd, my_message, len, 0, (struct sockaddr *)remoteAddressPtr, sizeof(*remoteAddressPtr)) != len) {
perror("sendto failed");
dispatch_source_cancel(writeSource);
}
});
dispatch_source_set_cancel_handler(writeSource, ^{
close(fd);
free(localAddressPtr);
free(remoteAddressPtr);
});
dispatch_resume(writeSource);
return 1;
}
NB: There's no way to dispose of the writeSource in my example without there being an error in a send operation. It's a trivial example...
My general theory on why NSLog triggers the handler to fire in your case, is that it keeps execution at or below that stack frame long enough for the background thread to come around and call the handler, but without that NSLog, your function returns, and something has a chance to die before the handler can get called. In fact, if you're using ARC it's probably the writeSource itself that is getting deallocated, since I don't see you making a strong reference to it anywhere outside the scope of this function. (My example captures a strong reference to it in the block, thus keeping it alive.) You could test this in your code by stashing a strong reference to writeSource.
I found the error:
In newer SDKs dispatch sources are subject to automatic reference counting despite the fact that they are no Objective-C objects.
So when the start method is over ARC disposes the dispatch source and they never get called.
NSLog delays the end of the start method in a way that the dispatch source triggers before the source gets disposed.

Transmission of float values over TCP/IP and data corruption

I have an extremely strange bug.
I have two applications that communicate over TCP/IP.
Application A is the server, and application B is the client.
Application A sends a bunch of float values to application B every 100 milliseconds.
The bug is the following: sometimes some of the float values received by application B are not the same as the values transmitted by application A.
Initially, I thought there was a problem with the Ethernet or TCP/IP drivers (some sort of data corruption). I then tested the code in other Windows machines, but the problem persisted.
I then tested the code on Linux (Ubuntu 10.04.1 LTS) and the problem is still there!!!
The values are logged just before they are sent and just after they are received.
The code is pretty straightforward: the message protocol has a 4 byte header like this:
//message header
struct MESSAGE_HEADER {
unsigned short type;
unsigned short length;
};
//orientation message
struct ORIENTATION_MESSAGE : MESSAGE_HEADER
{
float azimuth;
float elevation;
float speed_az;
float speed_elev;
};
//any message
struct MESSAGE : MESSAGE_HEADER {
char buffer[512];
};
//receive specific size of bytes from the socket
static int receive(SOCKET socket, void *buffer, size_t size) {
int r;
do {
r = recv(socket, (char *)buffer, size, 0);
if (r == 0 || r == SOCKET_ERROR) break;
buffer = (char *)buffer + r;
size -= r;
} while (size);
return r;
}
//send specific size of bytes to a socket
static int send(SOCKET socket, const void *buffer, size_t size) {
int r;
do {
r = send(socket, (const char *)buffer, size, 0);
if (r == 0 || r == SOCKET_ERROR) break;
buffer = (char *)buffer + r;
size -= r;
} while (size);
return r;
}
//get message from socket
static bool receive(SOCKET socket, MESSAGE &msg) {
int r = receive(socket, &msg, sizeof(MESSAGE_HEADER));
if (r == SOCKET_ERROR || r == 0) return false;
if (ntohs(msg.length) == 0) return true;
r = receive(socket, msg.buffer, ntohs(msg.length));
if (r == SOCKET_ERROR || r == 0) return false;
return true;
}
//send message
static bool send(SOCKET socket, const MESSAGE &msg) {
int r = send(socket, &msg, ntohs(msg.length) + sizeof(MESSAGE_HEADER));
if (r == SOCKET_ERROR || r == 0) return false;
return true;
}
When I receive the message 'orientation', sometimes the 'azimuth' value is different from the one sent by the server!
Shouldn't the data be the same all the time? doesn't TCP/IP guarantee delivery of the data uncorrupted? could it be that an exception in the math co-processor affects the TCP/IP stack? is it a problem that I receive a small number of bytes first (4 bytes) and then the message body?
EDIT:
The problem is in the endianess swapping routine. The following code swaps the endianess of a specific float around, and then swaps it again and prints the bytes:
#include <iostream>
using namespace std;
float ntohf(float f)
{
float r;
unsigned char *s = (unsigned char *)&f;
unsigned char *d = (unsigned char *)&r;
d[0] = s[3];
d[1] = s[2];
d[2] = s[1];
d[3] = s[0];
return r;
}
int main() {
unsigned long l = 3206974079;
float f1 = (float &)l;
float f2 = ntohf(ntohf(f1));
unsigned char *c1 = (unsigned char *)&f1;
unsigned char *c2 = (unsigned char *)&f2;
printf("%02X %02X %02X %02X\n", c1[0], c1[1], c1[2], c1[3]);
printf("%02X %02X %02X %02X\n", c2[0], c2[1], c2[2], c2[3]);
getchar();
return 0;
}
The output is:
7F 8A 26 BF
7F CA 26 BF
I.e. the float assignment probably normalizes the value, producing a different value from the original.
Any input on this is welcomed.
EDIT2:
Thank you all for your replies. It seems the problem is that the swapped float, when returned via the 'return' statement, is pushed in the CPU's floating point stack. The caller then pops the value from the stack, the value is rounded, but it is the swapped float, and therefore the rounding messes up the value.
TCP tries to deliver unaltered bytes, but unless the machines have similar CPU-s and operating-systems, there's no guarantee that the floating-point representation on one system is identical to that on the other. You need a mechanism for ensuring this such as XDR or Google's protobuf.
You're sending binary data over the network, using implementation-defined padding for the struct layout, so this will only work if you're using the same hardware, OS and compiler for both application A and application B.
If that's ok, though, I can't see anything wrong with your code. One potential issue is that you're using ntohs to extract the length of the message and that length is the total length minus the header length, so you need to make sure you setting it properly. It needs to be done as
msg.length = htons(sizeof(ORIENTATION_MESSAGE) - sizeof(MESSAGE_HEADER));
but you don't show the code that sets up the message...