I have twio problems,
I seem to be able to succesfully connect to my server on port 1514 but
I don't get any data sent off eventho the # of bytes sent match my
strlen...what's going on here. If i establish a telnet connection
manually it works just fine.
My code to connect to the server is as follows:
int connecttoserver(char *hostname,int port)
{
struct timeval tv;
struct sockaddr_in sa_server;
char host[255] = {0};
const struct hostent *host_info;
struct in_addr *address;
if (m_sock >= 0 )
{
shutdown(m_sock, SHUT_RDWR);
close(m_sock);
}
tv.tv_sec = 1;
tv.tv_usec = 0;
//Get ip from hostname
sprintf(host,"%s",hostname);
host_info = NULL;
host_info = gethostbyname(host);
if (host_info) {
address = (struct in_addr*)host_info->h_addr_list[0] ;
memset(host,0x00,sizeof(host)) ;
strcpy(host,inet_ntoa(*address)) ;
}
sa_server.sin_family = AF_INET;
sa_server.sin_port = htons(port);
sa_server.sin_addr.s_addr = inet_addr(host);
//open socket
m_sock = socket(AF_INET,SOCK_STREAM,0);
syslog(LOG_ERR, "nlog: got socket");
int bConnected = 0;
do
{
if (m_sock<0)
{
syslog(LOG_ERR, "nlog: Error creating socket.");
break;
}
if(setsockopt(m_sock, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv,
sizeof(tv)))
{
syslog(LOG_ERR, "nlog: Set socket send timeout fail");
break;
}
if(setsockopt(m_sock, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv,
sizeof(tv)))
{
syslog(LOG_ERR, "nlog: Set socket receive timeout fail");
break;
}
if (connect(m_sock,(struct sockaddr *)&sa_server,sizeof
(sa_server)) < 0)
{
syslog(LOG_ERR, "nlog: Connect to server fail");
break;
}
bConnected = 1;
} while (0);
m_opened = bConnected;
return m_opened;
}
And I send my data off like this:
if (m_sock>-1) {
int len=send(m_sock, res, strlen(res), 0);
if (len != strlen(res))
printf("nlog: \"%s\" not sent, strlen(%d) - sent %d\n",res,
strlen(res), len);
else
printf("sent %s\n-------------\n", res);
} else
printf("nlog: m_sock:%d",m_sock);
Where am I dpoing something wrong and why does it work just fine if i
establish a manual telnet?
Thanks for hints and suggestions!
Also I haven't looked yet how i can receive an acknowledge from the
server, the server would send me "LOGOK" back if it worked sucessfully.
> Hi There,
>
> I have twio problems,
>
> I seem to be able to succesfully connect to my server on port 1514 but
> I don't get any data sent off eventho the # of bytes sent match my
> strlen...what's going on here. If i establish a telnet connection
> manually it works just fine.
What makes you think it's not sending the data? Is it because the
server doesn't report receiving it, or have you used a packet capture
program to see what's being sent and receied?
> My code to connect to the server is as follows:
> int connecttoserver(char *hostname,int port)
> {
> struct timeval tv;
> struct sockaddr_in sa_server;
> char host[255] = {0};
> const struct hostent *host_info;
> struct in_addr *address;
>
> if (m_sock >= 0 )
> {
> shutdown(m_sock, SHUT_RDWR);
> close(m_sock);
> }
>
> tv.tv_sec = 1;
> tv.tv_usec = 0;
> //Get ip from hostname
> sprintf(host,"%s",hostname);
> host_info = NULL;
> host_info = gethostbyname(host);
> if (host_info) {
> address = (struct in_addr*)host_info->h_addr_list[0] ;
> memset(host,0x00,sizeof(host)) ;
> strcpy(host,inet_ntoa(*address)) ;
> }
>
> sa_server.sin_family = AF_INET;
> sa_server.sin_port = htons(port);
> sa_server.sin_addr.s_addr = inet_addr(host);
Why do you convert the address to a string, and then back to an address?
Why not just copy *address directly into sa_server.sin_addr.s_addr?
--
Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
That's one problem. If the return value from send is equal to the
length parameter and the length was larger than zero, something should
be send. Judging from reading through this once, there are no obvious
errors.
A few comments on the code in general:
> int connecttoserver(char *hostname,int port)
> {
> struct timeval tv;
> struct sockaddr_in sa_server;
> char host[255] = {0};
That's useless.
> const struct hostent *host_info;
> struct in_addr *address;
>
> if (m_sock >= 0 )
> {
> shutdown(m_sock, SHUT_RDWR);
> close(m_sock);
> }
>
> tv.tv_sec = 1;
> tv.tv_usec = 0;
> //Get ip from hostname
> sprintf(host,"%s",hostname);
> host_info = NULL;
> host_info = gethostbyname(host);
> if (host_info) {
> address = (struct in_addr*)host_info->h_addr_list[0] ;
> memset(host,0x00,sizeof(host)) ;
> strcpy(host,inet_ntoa(*address)) ;
> }
>
> sa_server.sin_family = AF_INET;
> sa_server.sin_port = htons(port);
> sa_server.sin_addr.s_addr = inet_addr(host);
inet_ntoa and inet_addr are the inverse of each other, meaning, you
get a struct in_addr from gethostbyname, convert that to a textual
'dotted quad' form (eg 1.2.3.4) and convert that back to a struct
in_addr.
> //open socket
> m_sock = socket(AF_INET,SOCK_STREAM,0);
> syslog(LOG_ERR, "nlog: got socket");
>
> int bConnected = 0;
>
> do
> {
> if (m_sock<0)
> {
> syslog(LOG_ERR, "nlog: Error creating socket.");
> break;
This is a bad way to report errors and leads to lots of duplicated
code. A better solution would be to have a single error reporting
statement and pass the call which failed as argument, eg
char *sysc;
m_sock = socket(...);
if (m_sock == -1) {
sysc = "socket"
goto error;
}
.
.
.
error:
syslog(LOG_ERR, "%s: %s: %m(%d)", __func__, sysc, errno);
This will result in an error message like the template below
<name of function>: <name of system function>: <standard errormessage>(<error number>)
NB: This is just the minium amount of information I like to have for
debugging.
> if(setsockopt(m_sock, SOL_SOCKET, SO_SNDTIMEO, (void *)&tv,
> sizeof(tv)))
> {
> syslog(LOG_ERR, "nlog: Set socket send timeout fail");
> break;
> }
This is a bad idea. Let the TCP-code in the kernel deal with timeouts.
>
> if(setsockopt(m_sock, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv,
> sizeof(tv)))
This is a bad idea. Let the TCP-code in the kernel deal with timeouts
(Programmiererkontrollwahn tut selten gut).
[...]
> And I send my data off like this:
> if (m_sock>-1) {
> int len=send(m_sock, res, strlen(res), 0);
> if (len != strlen(res))
Don't call strlen for the same string repeatedly. This is a not 'a
function' in the mathematical sense, IOW, equivalent to the string
length, but a subroutine which counts the number of bytes until a 0 in
the buffer pointed-to by res. Don't count on being able to always have
the pleasure of using a compiler which doesn't comply with the
ELF-standard in order to make programming easier for people who cannot
ever get their head out of math. And even this compiler cannot really
help you. And don't use send except if you actually want to do
something a simple write cannot.
If I send the same data with a simple "telnet nems 1514" i see them
properly being received.
However data sent from within my app do not show up... :(
My connect function looks differently all together now:
int connecttoserver(char *hostname,int port)
{
struct hostent *he;
struct sockaddr_in server;
struct protoent *pr;
if (m_sock >= 0 )
{
shutdown(m_sock, SHUT_RDWR);
close(m_sock);
}
/* resolve localhost to an IP (should be 127.0.0.1) */
if ((he = gethostbyname(hostname)) == NULL) {
puts("error resolving hostname..");
exit(1);
}
/*
* copy the network address part of the structure to the
* sockaddr_in structure which is passed to connect()
*/
memcpy(&server.sin_addr, he->h_addr_list[0], he->h_length);
server.sin_family = AF_INET;
server.sin_port = htons(port);
pr = getprotobyname("tcp");
if (!pr) {
printf("getpotobyname() failed...exit!\n");
exit(1);
}
/* create socket */
if ( (m_sock = socket(PF_INET, SOCK_STREAM, pr->p_proto)) == -1) {
printf("error creating socket...exit,errno: %s!\n", strerror
( errno ));
exit(1);
}
/* connect */
if (connect(m_sock, (struct sockaddr *)&server, sizeof(server))) {
printf("error connecting...exit,errno: %s!\n", strerror( errno ));
exit(1);
}
return m_sock;
}
Okay, If I look with Wireshark, I see some of my data going to my
destination ip but why would they show up nicely if i telnet but not
if they're sent from my app? :o
Ah, I just figured it out, I needed to strcat() two newlines at the
end of my string. :) Sweet! Thanks for your help! :)
> Ah, I just figured it out, I needed to strcat() two newlines at the
> end of my string. :) Sweet! Thanks for your help! :)
Why would that make a difference? Socket software doesn't care about
newlines.
Is it because the receiving application isn't doing anything until it
gets a newline? But why do you need TWO newlines?
Seconded. It could just be weird logic, or it could be something really
scary.
-Beej
Probably because the receiving app is looking for CRLF, but is happy with LFLF (i.e. ignores
the CR byte).
> Ah, I just figured it out, I needed to strcat() two newlines at the
> end of my string. :) Sweet! Thanks for your help! :)
Are you implementing some protocol that has a specification? If not,
that's a bad idea. If so, what does it say should be used as a line
ending?
The reason you need a protocol specification is because otherwise,
problems like this aren't solvable. Perhaps two newlines will break
things when you connect to some other server that's actually expecting
CRLF. Without a specification, you may find that you can't find a way
to make one end work with two or three different implementation of the
other end and you have no idea who or what is at fault.
With a specification, it's always clear what should be done and who is
at fault. That saves a lot of pain.
DS