An interesting problem with accept()
Hello, I'd recently been trying something with the unix sockets and I
need some help with my accept functions extraordinary behaviour.
First of all, my native operating system is Windows XP and I also run
a ubuntu server edition on VMWare.
I've written two programs. One is server and other is client. What the
server does is simple, it just displays messages received from the
client, and what the client does is sending messages to server. The
server runs under ubuntu server (vmware) and the client runs under
windows.
Here is the code of the server (the one runs under linux) :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORTNO 5050
int read_socket(int s, void *pBuf, int n);
int main()
{
int serverSocket, clientSocket;
struct sockaddr_in sinServer, sinClient;
int client_addrlen;
if ((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Cannot create socket!");
exit(EXIT_FAILURE);
}
sinServer.sin_family = AF_INET;
sinServer.sin_port = htons(PORTNO);
sinServer.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(serverSocket, (const struct sockaddr *)&sinServer, sizeof
sinServer) == -1) {
perror("Cannot bind socket!");
exit(EXIT_FAILURE);
}
if (listen(serverSocket, 8) == -1) {
perror("Cannot listen!");
exit(EXIT_FAILURE);
}
printf("Waiting for connection!\n");
if ((clientSocket = accept(serverSocket, (struct sockaddr *)
&sinClient, &client_addrlen)) == -1) {
perror("Cannot accept!");
exit(EXIT_FAILURE);
}
printf("Connected!\n");
printf("Client IP = %s\n", inet_ntoa(sinClient.sin_addr));
printf("Client port = %d\n", ntohs(sinClient.sin_port));
{
char s[32];
for (;;) {
read_socket(clientSocket, s, sizeof s);
puts(s);
if (!strcmp(s, "quit"))
break;
}
}
shutdown(serverSocket, SHUT_RDWR);
return 0;
}
int read_socket(int s, void *pBuf, int n)
{
int result;
int index = 0;
int left = n;
while (left > 0) {
result = recv(s, (char *)pBuf + index, left, 0);
if (result == 0)
return index;
if (result == -1)
return index;
index += result;
left -= result;
}
return index;
}
And here is the code of client (one that runs under windows) :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#define PORTNO 5050
int write_socket(SOCKET s, const void *pBuf, int n);
int main()
{
WSADATA wsd;
int result;
SOCKET serverSocket;
struct sockaddr_in sinServer;
char hostname[] = "192.168.71.128"; /*IP address of vmware, when i
write ifconfig under vmware, this is shown. */
struct hostent *host;
if ((result = WSAStartup(MAKEWORD(2, 2), &wsd)) != 0) {
fprintf(stderr, "Cannot load winsock library: %d\n", result);
exit(EXIT_FAILURE);
}
if ((serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) ==
INVALID_SOCKET) {
fprintf(stderr, "Cannot create socket: %d\n", WSAGetLastError());
exit(EXIT_FAILURE);
}
sinServer.sin_family = AF_INET;
sinServer.sin_port = htons(PORTNO);
sinServer.sin_addr.s_addr = inet_addr(hostname);
if (sinServer.sin_addr.s_addr == INADDR_NONE) {
host = gethostbyname(hostname);
if (host == NULL) {
fprintf(stderr, "Cannot resolve hostname: %s\n", hostname);
exit(EXIT_FAILURE);
}
memcpy(&sinServer.sin_addr.s_addr, host->h_addr_list[0], host-[color=blue]
>h_length);[/color]
}
if (connect(serverSocket, (const struct sockaddr *)&sinServer, sizeof
sinServer) == SOCKET_ERROR) {
fprintf(stderr, "Cannot connect to server!: %d\n",
WSAGetLastError());
exit(EXIT_FAILURE);
}
{
char s[32];
for (;;) {
printf("Text: ");
gets(s);
write_socket(serverSocket, s, sizeof s);
if (!strcmp(s, "quit"))
break;
}
}
WSACleanup();
return 0;
}
int write_socket(SOCKET s, const void *pBuf, int n)
{
int result;
int index = 0;
int left = n;
while (left > 0) {
result = send(s, (const char *)pBuf + index, left, 0);
if (result == 0)
return index;
if (result == SOCKET_ERROR)
return index;
index += result;
left -= result;
}
return index;
}
interesting point here is that. when i run server under linux and
after run client under windows, server prints the message "Cannot
accept!: Invalid Arguement" and stops running. When i comment out the
block after accept (which is { char s[32] and bla bla..} ) it just
connects. (prints connected and prints an ip and a port number, then
quits.)
How is it possible? Why does it not connect when i don't comment out
the infinite-loop part?
Re: An interesting problem with accept()
I suspect this is it:
hayri ugur koltuk <ugurkoltuk@gmail.com> writes:
[...]
[color=blue]
> if ((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
> perror("Cannot create socket!");
> exit(EXIT_FAILURE);
> }
>[/color]
[...]
[color=blue]
> if ((clientSocket = accept(serverSocket, (struct sockaddr *)
> &sinClient, &client_addrlen)) == -1) {
> perror("Cannot accept!");
> exit(EXIT_FAILURE);
> }[/color]
[...]
[color=blue]
> char s[32];
>
> for (;;) {
> read_socket(clientSocket, s, sizeof s);
> puts(s);
> if (!strcmp(s, "quit"))
> break;
> }[/color]
[...]
[color=blue]
> shutdown(serverSocket, SHUT_RDWR);[/color]
After the client connects, you're shutting down the server socket
instead of the client socket.
Also, I think there are a few problems with your read_socket. First,
after calling it you are using functions which take a NUL-terminated
string, like puts and strcmp, but I don't see anything making sure
there is a NUL at the end. And it looks like your server is reading
until it gets 32 characters or end-of-file, but the client seems to be
sending data line-at-a-time. Maybe you are always sending one line
the EOF, so it works, but it seems somewhat unusual.
Hope this helps,
----Scott.
Re: An interesting problem with accept()
In article <649a4dd7-4a10-4cb1-92de-dd4e5e01fb6d@m44g2000hsc.googlegroups.com>, [email]ugurkoltuk@gmail.com[/email] (hayri ugur koltuk) writes:
| Hello, I'd recently been trying something with the unix sockets and I
| need some help with my accept functions extraordinary behaviour.
You are not initializing client_addrlen.
Dan Lanciani
ddl@danlan.*com
Re: An interesting problem with accept()
On Jun 15, 10:23*pm, ddl@danlan.*com (Dan Lanciani) wrote:[color=blue]
> In article <649a4dd7-4a10-4cb1-92de-dd4e5e01f...@m44g2000hsc.googlegroups..com>, ugurkol...@gmail.com (hayri ugur koltuk) writes:
>
> | Hello, I'd recently been trying something with the unix sockets and I
> | need some help with my accept functions extraordinary behaviour.
>
> You are not initializing client_addrlen.
>[/color]
Why would not initializing client_addrlen matter when doing call by
value-result?
Chad
Re: An interesting problem with accept()
In article
<9dab91e5-b2b3-4d48-9c3a-b0fd3b87e9dc@i36g2000prf.googlegroups.com>,
grocery_stocker <cdalten@gmail.com> wrote:
[color=blue]
> On Jun 15, 10:23*pm, ddl@danlan.*com (Dan Lanciani) wrote:[color=green]
> > In article
> > <649a4dd7-4a10-4cb1-92de-dd4e5e01f...@m44g2000hsc.googlegroups.com>,
> > ugurkol...@gmail.com (hayri ugur koltuk) writes:
> >
> > | Hello, I'd recently been trying something with the unix sockets and I
> > | need some help with my accept functions extraordinary behaviour.
> >
> > You are not initializing client_addrlen.
> >[/color]
>
> Why would not initializing client_addrlen matter when doing call by
> value-result?[/color]
From the man page:
The address_len is a value-result parameter; it should initially
contain the amount of space pointed to by address; on return it
will contain the actual length (in bytes) of the address returned.
--
Barry Margolin, [email]barmar@alum.mit.edu[/email]
Arlington, MA
*** PLEASE don't copy me on replies, I'll read them in the group ***
Re: An interesting problem with accept()
On Jun 19, 6:36*pm, Barry Margolin <bar...@alum.mit.edu> wrote:[color=blue]
> In article
> <9dab91e5-b2b3-4d48-9c3a-b0fd3b87e...@i36g2000prf.googlegroups.com>,
>
> *grocery_stocker <cdal...@gmail.com> wrote:[color=green]
> > On Jun 15, 10:23*pm, ddl@danlan.*com (Dan Lanciani) wrote:[color=darkred]
> > > In article
> > > <649a4dd7-4a10-4cb1-92de-dd4e5e01f...@m44g2000hsc.googlegroups.com>,
> > > ugurkol...@gmail.com (hayri ugur koltuk) writes:[/color][/color]
>[color=green][color=darkred]
> > > | Hello, I'd recently been trying something with the unix sockets and I
> > > | need some help with my accept functions extraordinary behaviour.[/color][/color]
>[color=green][color=darkred]
> > > You are not initializing client_addrlen.[/color][/color]
>[color=green]
> > Why would not initializing client_addrlen matter when doing call by
> > value-result?[/color]
>
> From the man page:
>
> * * *The address_len is a value-result parameter; it should initially
> * * *contain the amount of space pointed to by address; on return it
> * * *will contain the actual length (in bytes) of the address returned.
>
> --[/color]
Why would not intializing client_addrlen matter? client_addrlen is
going to get the correct value when the function returns. If there is
a failure, wouldn't the error get copied over to client_addrlen and
hence overwrite the unitialized value of client_addrlen?
Chad
Re: An interesting problem with accept()
grocery_stocker wrote:[color=blue]
> On Jun 19, 6:36 pm, Barry Margolin <bar...@alum.mit.edu> wrote:[color=green]
>> In article
>> <9dab91e5-b2b3-4d48-9c3a-b0fd3b87e...@i36g2000prf.googlegroups.com>,
>>
>> grocery_stocker <cdal...@gmail.com> wrote:[color=darkred]
>>> On Jun 15, 10:23 pm, ddl@danlan.*com (Dan Lanciani) wrote:
>>>> In article
>>>> <649a4dd7-4a10-4cb1-92de-dd4e5e01f...@m44g2000hsc.googlegroups.com>,
>>>> ugurkol...@gmail.com (hayri ugur koltuk) writes:
>>>> | Hello, I'd recently been trying something with the unix sockets and I
>>>> | need some help with my accept functions extraordinary behaviour.
>>>> You are not initializing client_addrlen.
>>> Why would not initializing client_addrlen matter when doing call by
>>> value-result?[/color]
>> From the man page:
>>
>> The address_len is a value-result parameter; it should initially
>> contain the amount of space pointed to by address; on return it
>> will contain the actual length (in bytes) of the address returned.[/color]
>
> Why would not intializing client_addrlen matter?[/color]
A value-result parameter means the value pointed to is used, as well as
(possibly) being updated by the function. In this particular case,
accept() will check the value pointed to is no smaller than the size of
the address, and fail if it isn't.
Alex
Re: An interesting problem with accept()
On Fri, 20 Jun 2008 12:51:34 -0700, grocery_stocker wrote:
[color=blue]
> Why would not intializing client_addrlen matter? client_addrlen is going
> to get the correct value when the function returns. If there is a
> failure, wouldn't the error get copied over to client_addrlen and hence
> overwrite the unitialized value of client_addrlen?[/color]
Because the function wants to know if you allocated enough memory for the
value it wants to store. Otherwise it has to assume this and if you
didn't allocate enough memory, something will get corrupted.
M4
Re: An interesting problem with accept()
On Jun 20, 1:36*pm, Martijn Lievaart <m...@rtij.nl.invlalid> wrote:[color=blue]
> On Fri, 20 Jun 2008 12:51:34 -0700, grocery_stocker wrote:[color=green]
> > Why would not intializing client_addrlen matter? client_addrlen is going
> > to get the correct value when the function returns. If there is a
> > failure, wouldn't the error get copied over to client_addrlen and hence
> > overwrite the unitialized value of client_addrlen?[/color]
>
> Because the function wants to know if you allocated enough memory for the
> value it wants to store. Otherwise it has to assume this and if you
> didn't allocate enough memory, something will get corrupted.
>[/color]
I didn't know it was possible to allocate memory using something like
sizeof().
Re: An interesting problem with accept()
grocery_stocker wrote:
[color=blue]
> On Jun 20, 1:36*pm, Martijn Lievaart <m...@rtij.nl.invlalid> wrote:[color=green]
>> On Fri, 20 Jun 2008 12:51:34 -0700, grocery_stocker wrote:[color=darkred]
>> > Why would not intializing client_addrlen matter? client_addrlen is
>> > going to get the correct value when the function returns. If there
>> > is a failure, wouldn't the error get copied over to client_addrlen
>> > and hence overwrite the unitialized value of client_addrlen?[/color]
>>
>> Because the function wants to know if you allocated enough memory for
>> the value it wants to store. Otherwise it has to assume this and if
>> you didn't allocate enough memory, something will get corrupted.
>>[/color]
>
> I didn't know it was possible to allocate memory using something like
> sizeof().[/color]
Sizeof is evaluated at compile time, so you can use it in allocating
dynamic memory (with malloc and friends) but you can't use it for
static allocations (though with C99 you can use it with Variable Length
Arrays.)
Re: An interesting problem with accept()
santosh wrote:
[color=blue]
> Sizeof is evaluated at compile time, so you can use it in allocating
> dynamic memory (with malloc and friends) but you can't use it for
> static allocations (though with C99 you can use it with Variable Length
> Arrays.)[/color]
/* BEGIN new.c */
#include <stdio.h>
int main (void)
{
static char array[sizeof (char)];
if (sizeof array == 1) {
puts("What do you mean by "
"\"can't use it for static allocations\"?");
}
return 0;
}
/* END new.c */
--
pete
Re: An interesting problem with accept()
santosh <santosh.k83@gmail.com> writes:
[color=blue]
> grocery_stocker wrote:
>[color=green]
>> On Jun 20, 1:36Â*pm, Martijn Lievaart <m...@rtij.nl.invlalid> wrote:[color=darkred]
>>> On Fri, 20 Jun 2008 12:51:34 -0700, grocery_stocker wrote:
>>> > Why would not intializing client_addrlen matter? client_addrlen is
>>> > going to get the correct value when the function returns. If there
>>> > is a failure, wouldn't the error get copied over to client_addrlen
>>> > and hence overwrite the unitialized value of client_addrlen?
>>>
>>> Because the function wants to know if you allocated enough memory for
>>> the value it wants to store. Otherwise it has to assume this and if
>>> you didn't allocate enough memory, something will get corrupted.
>>>[/color]
>>
>> I didn't know it was possible to allocate memory using something like
>> sizeof().[/color]
>
> Sizeof is evaluated at compile time, so you can use it in allocating
> dynamic memory (with malloc and friends) but you can't use it for
> static allocations (though with C99 you can use it with Variable Length
> Arrays.)[/color]
I am not sure what you mean by "static allocation", but sizeof can be
used as part of an array size (with some restriction) in almost all
cases. You can certainly use it for automatic arrays, file-scope
arrays and arrays with the static storage class specifier.
To get a VLA from it you'd need to take the size of another VLA object
or include in the expression some term that is not a compile-time
constant.
--
Ben.