LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-01-2006, 12:31 PM   #1
Yury
LQ Newbie
 
Registered: Aug 2006
Location: Ukraine
Distribution: Debian Etch
Posts: 15

Rep: Reputation: 0
Post sendto: invalid argument


I know this is very basic question, but i really need a little help here :\
In my program i have function mysend(), which is a wrapper to sendto() call:
Code:
void mysend(const char *sendstring, const struct sockaddr_in *addr){
  int sendstringlen = strlen(sendstring);
  if(sendto(main_socket, sendstring, sendstringlen, 0, addr, sizeof(struct sockaddr_in)) == -1){
    perror("sendto");
  }
  
}
The main_socket is UDP socket.
I also have a global struct sockaddr_in current, which represents address of the machine i currently communicate with. This stucture is already filled by the recvfrom(...) call.
But when i call mysend("hello",&current); it prints error: sendto: invalid argument.
I just can't find where the mistake is... :\
P.S. my platform is Gnu/Linux
 
Old 11-01-2006, 12:44 PM   #2
nadroj
Senior Member
 
Registered: Jan 2005
Location: Canada
Distribution: ubuntu
Posts: 2,539

Rep: Reputation: 60
do all your parameters' type match the required:
Code:
int sendto(int, const char *, size_t, int, struct sockaddr *, size_t);
 
Old 11-01-2006, 12:59 PM   #3
Mara
Moderator
 
Registered: Feb 2002
Location: Grenoble
Distribution: Debian
Posts: 9,696

Rep: Reputation: 232Reputation: 232Reputation: 232
Code:
  if(sendto(main_socket, sendstring, sendstringlen, 0, (struct sockaddr *)addr, sizeof(struct
struct sockaddr and struct sockaddr_in are compatibile, so you can cast one to another, but they're still different types, that's why casting is required.
 
Old 11-01-2006, 04:31 PM   #4
Yury
LQ Newbie
 
Registered: Aug 2006
Location: Ukraine
Distribution: Debian Etch
Posts: 15

Original Poster
Rep: Reputation: 0
Exclamation

Hmm, added (struct sockaddr *), but it still returns an error
Strange behavior, isn't it?
Anyway, thanks for help
 
Old 11-01-2006, 04:34 PM   #5
nadroj
Senior Member
 
Registered: Jan 2005
Location: Canada
Distribution: ubuntu
Posts: 2,539

Rep: Reputation: 60
then one of the other parameters is wrong. the first parameter says its supposed to be 'int', is main_socket of type 'int'??
 
Old 11-01-2006, 04:43 PM   #6
Yury
LQ Newbie
 
Registered: Aug 2006
Location: Ukraine
Distribution: Debian Etch
Posts: 15

Original Poster
Rep: Reputation: 0
Unfortunately it is int

Last edited by Yury; 11-01-2006 at 04:45 PM.
 
Old 11-01-2006, 07:23 PM   #7
nadroj
Senior Member
 
Registered: Jan 2005
Location: Canada
Distribution: ubuntu
Posts: 2,539

Rep: Reputation: 60
can you change sendstring to &sendstring does that help? (?)

Last edited by nadroj; 11-01-2006 at 07:37 PM.
 
Old 11-01-2006, 07:24 PM   #8
orgcandman
Member
 
Registered: May 2002
Location: new hampshire
Distribution: Fedora, RHEL
Posts: 600

Rep: Reputation: 110Reputation: 110
can you post how you're filling up the sockaddr_in struct?
 
Old 11-02-2006, 03:34 PM   #9
Mara
Moderator
 
Registered: Feb 2002
Location: Grenoble
Distribution: Debian
Posts: 9,696

Rep: Reputation: 232Reputation: 232Reputation: 232
I have made a short test. The code below compiles fine:
Code:
#include <string.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main_socket = -1;

void mysend(const char *sendstring, const struct sockaddr_in *addr){
  int sendstringlen = strlen(sendstring);
  if(sendto(main_socket, sendstring, sendstringlen, 0, (struct sockaddr *)add
    perror("sendto");
  }
}

int main(int argc, char **argv)
{
  struct sockaddr_in sock;
  mysend("blah", &sock);
  return 0;
}
 
Old 11-02-2006, 04:47 PM   #10
Yury
LQ Newbie
 
Registered: Aug 2006
Location: Ukraine
Distribution: Debian Etch
Posts: 15

Original Poster
Rep: Reputation: 0
Ok, i'll go little deeper.
Let's take the main_socket first.
Here is how it was declared:
Code:
int main_socket;
Later it has been manipulated by this function:
Code:
int create_socket(uint16_t port){
  /* Create a new socket unit */
  int sock = socket(AF_INET, SOCK_DGRAM, 0);
  struct sockaddr_in main_socket_name;
  main_socket_name.sin_family = AF_INET;
  main_socket_name.sin_port = htons(port);
  main_socket_name.sin_addr.s_addr = htonl(INADDR_ANY);
  
  /* Bind it to port */
  if(bind(sock, (struct sockaddr *) &main_socket_name, sizeof(main_socket_name)) < 0){
    perror("bind");
    exit(EXIT_FAILURE);
  }

  
  return sock;
}
And assigned:
Code:
...
  main_socket = create_socket(port); // port - global variable, == 4242 if user did not change it.
  ...
Now let's see what we have about sendstring.
It is assigned when i call the function mysend():
Code:
...
  mysend("hello",&currend);
  ...
Tried to change sendstring to &sendstring but it did not help
The int sendstringlen is strlen(sendstring).
And the most interesting and important part - struct sockaddr_in current.
Declaration:
Code:
struct sockaddr_in current;
It was initially filled in this way:
Code:
void myrecv(const struct sockaddr_in *addr){
  int addrlen = sizeof(struct sockaddr_in);
  buflen = recvfrom(main_socket, buffer, BUFSIZE, 0, (struct sockaddr *)addr, &addrlen);
  if(buflen == -1){
    perror("recvfrom");
  }
}
Code:
...
  myrecv(&current);
  ...
When someone connects, it sends the following: NEW myname, where myname is his id.
I successully receive this message, and call the client_new(char * login) function, which allocates memory for this guy and saves his id in that memory. When it is done, i should send him "hello" message:
Code:
mysend("hello",&current);
What happens later we already know
That stupid bug seems to be somewhere deeper. But where?????
I test this server with simple client written in python, here is the code:
Code:
#!/usr/bin/python

import socket
import sys

# Collect info
username = raw_input("Your login plz: ")
servername = raw_input("Server hostname: ")
serverport = raw_input("And port plz (default: 4242) : ")
if serverport == "":
	serverport = 4242
else: serverport = int(serverport)

serveraddr = ((servername, serverport))

# Have info, connect to the server
print "Connecting..."

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# Send login info
sock.sendto("NEW %s" % username, serveraddr)
helloconfirm = sock.recv(256) # Here the server should send me "hello" message.
# Bug in the server! All i can do now is to kill this program.

# Send all what user types in, print all that server sends in
io = select((sys.stdin, sock), Null, Null, Null)
while(1):
	if io[0] == sys.stdin:
		# User typed something in termintal. Send it to the server
		str = raw_input()
		if str == "quit":
			sock.close()
			exit(0)

		sock.sendto(str, serveraddr)
	else:
		# Server sent something in. Print it
		str = sock.recv(256)
		print str
It seems to be all.
 
Old 11-03-2006, 12:00 PM   #11
Yury
LQ Newbie
 
Registered: Aug 2006
Location: Ukraine
Distribution: Debian Etch
Posts: 15

Original Poster
Rep: Reputation: 0
Added the following to the mysend function:
Code:
  if(debug){ // debug == 1
    printf("main_socket == %d\n", main_socket);
    printf("addr->sin_addr.s_addr == %d\n", addr->sin_addr.s_addr);
    /* Tried also to use the inet_ntoa() function here but it causes a segfault. */
  }
Here is what it prints when run:
Code:
main_socket == 4
addr->sin_addr.s_addr == 0 //??????
sendto: Invalid argument
Also tested this trough eth0 interface (i used loopback before) and this does not changed anything.
 
Old 11-03-2006, 01:44 PM   #12
orgcandman
Member
 
Registered: May 2002
Location: new hampshire
Distribution: Fedora, RHEL
Posts: 600

Rep: Reputation: 110Reputation: 110
The answer is simple enough, I think.

Basically, you're assuming that the sockaddr_in is being correct assigned, but there is where you're incorrect.

On the stack, in myrecv(const struct sockaddr_in *addr), you are only modifying the local copy of addr. Try this, make it a **, use a local temporary copy (struct sockaddr *pSA = (sockaddr*)(*addr) that you pass to the function, and then memcpy it back (if(*addr != pSA)memcpy(*addr, pSA, sizeof(struct sockaddr)) and see if that works. My guess is that it will.

If that doesn't work, please post a full transcript of the program so that I can see exactly what happens.

-Aaron
 
Old 11-04-2006, 06:06 AM   #13
Yury
LQ Newbie
 
Registered: Aug 2006
Location: Ukraine
Distribution: Debian Etch
Posts: 15

Original Poster
Rep: Reputation: 0
It works!
I did not add the struct *pSA because the ** is too complicated for me(newbie in programming), thanx anyway for pointing where the problem is.
Here's what i did:
1. changed struct sockaddr_in current to struct sockaddr_in *current.
2. used malloc(sizeof(struct sockaddr_in)) to allocate memory for it.
3. current is now address of struct sockaddr_in in memory, so i don't need to do &current anymore:
Code:
myrecv(current);
Code:
mysend("hello",current);
And i was surprised when it started to work

Thank You guys for support, see ya.

Last edited by Yury; 11-04-2006 at 06:13 AM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Accept(): Invalid Argument bonhomme Programming 6 07-14-2012 10:12 PM
Invalid Argument Error ahmedb72 Red Hat 1 02-25-2006 07:52 AM
alsamixer invalid argument subaruwrx Linux - Software 1 03-12-2005 01:34 PM
KDSKBENT: Invalid Argument tommytomato Linux - Newbie 6 08-27-2004 10:23 PM
[ Invalid Argument on 'iptables' ] benleung Linux - Security 1 09-23-2003 12:25 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:10 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration