LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
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 12-12-2011, 07:51 AM   #1
golden_boy615
Member
 
Registered: Dec 2008
Distribution: Ubuntu Fedora
Posts: 445

Rep: Reputation: 18
socket programming problem


hello
I am newbie in socket programming and I wrote an example for practicing but it does nut work the code is:
Code:
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>

#define DEFAULT_PROTOCOL 0

int writerecipe(int fd)
{
    static char* line1 = "spam spam ,spam,spam,";
    static char* line2 = "2spam 2spam ,2spam,2spam.";

    if (write(fd,line1,strlen(line1)+1)==0)
    {
            printf("ok1\n");

    }
    if (write(fd,line2,strlen(line2)+1)==0)
    {
            printf("ok2\n");

    }
    return 0;
}

int readline(int fd,char* str)
{
    int n;

    do
    {
        n=read(fd,str,1);
    }
    while(n>0 && *str++ !=0);
     return(n>0);
}
int readrecipe(int fd)
{
    char str[200];
    while(readline(fd,str))
        printf("%s\n",str);
    return 0;
}

int main()
{
    int serverfd,clientfd;

    socklen_t serverlen,clientlen;
    struct sockaddr_un serveraddr;
    struct sockaddr_un clientaddr;

    struct sockaddr* serversockaddrptr;
    struct sockaddr* clientsockaddrptr;

    signal(SIGCHLD,SIG_IGN);
    serversockaddrptr=(struct sockaddr*) &serveraddr;
    serverlen=sizeof(serveraddr);

    clientsockaddrptr=(struct sockaddr*) &clientaddr;
    clientlen=sizeof(clientaddr);

    serverfd=socket(PF_LOCAL,SOCK_STREAM,DEFAULT_PROTOCOL);
    serveraddr.sun_family=PF_LOCAL;

    strcpy(serveraddr.sun_path,"recipe");
    bind(serverfd,serversockaddrptr,serverlen);

    listen(serverfd,5);

    while(1)
    {
        sleep(1);
        clientfd=accept(serverfd,clientsockaddrptr,&clientlen);
        if (fork()==0)
        {
                if (clientfd>0)
                {
                    printf("1\n");
                    writerecipe(clientfd);
                    close(clientfd);
                    exit(0);


                }
                else
                {
                    printf("nok1\n");
                }

        }
        else
        {
            close(clientfd);
            int clientfd2,result;

            socklen_t serverlen2;
            struct sockaddr_un serveraddr2;

            struct sockaddr* serversockaddrptr2;

            serversockaddrptr2=(struct sockaddr*) &serveraddr2;
            serverlen2=sizeof(serveraddr2);

            clientfd2=socket(PF_LOCAL,SOCK_STREAM,DEFAULT_PROTOCOL);
            serveraddr2.sun_family=PF_LOCAL;

            strcpy(serveraddr2.sun_path,"recipe");
            do
            {
                result=connect(clientfd2,serversockaddrptr2,serverlen2);
                if(result==-1)
                sleep(2);
            }
            while(result==-1);

            readrecipe(clientfd2);
            close(clientfd2);
        }
    }
it made up of two process that one of them is writing to a local socket and the other reading the socket and prints the contents.
but it does not work.

thanks for any help.
 
Old 12-12-2011, 08:43 AM   #2
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Could you please specify what exactly "does not work"?

With a quick glance at your code, I'm curious as to why you chose to insert the accept() call within the common area of the server/client code? This call should only be made by the server. Also, the sleep() call probably serves no purpose, and should be removed.

Consider something like:
Code:
...

if (fork() == 0)
{
   /* server */
   int clientfd = accept(...);   /* this will block, unless using non-blocking socket */

   if (clientfd > 0)
   {
      /* handle client */
      ...
   }
}
else
{
   /* client runs here */
   ...
   int result = connect(...);
   ...
}
From what I can tell, the issue you are having is not so much with socket programming, but with using fork(). Perhaps you should attempt to develop the client and server functionality in separate apps. Once you have that working, then consider going with the multi-process approach.

P.S. write() returns the number of bytes written. If you ask this function to write N-bytes, where N > 0, and a result of 0 is returned, I would say the call "failed", although a -1 is really the determining result for an error. In your code, you seem to think otherwise.

Last edited by dwhitney67; 12-13-2011 at 06:04 AM.
 
Old 12-12-2011, 03:50 PM   #3
devnull10
Member
 
Registered: Jan 2010
Location: Lancashire
Distribution: Slackware Stable
Posts: 572

Rep: Reputation: 120Reputation: 120
The following website is an excellent resource for socket programming.

http://beej.us/guide/bgnet/
 
1 members found this post helpful.
Old 12-13-2011, 12:31 AM   #4
golden_boy615
Member
 
Registered: Dec 2008
Distribution: Ubuntu Fedora
Posts: 445

Original Poster
Rep: Reputation: 18
thanks for your reply my problem is that accept call does not wait for connection and it returns with failure and prints:
Quote:
nok1
nok1
nok1
nok1
nok1
nok1
nok1
nok1
nok1
.
.
.
so I putted sleep in that to preventing fast while busy waiting .
and I deleted the fork and client section but the problem still exist:
Code:
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>

#define DEFAULT_PROTOCOL 0

int writerecipe(int fd)
{
    static char* line1 = "spam spam ,spam,spam,";
    static char* line2 = "2spam 2spam ,2spam,2spam.";

    if (write(fd,line1,strlen(line1)+1)==0)
    {
            printf("ok1\n");

    }
    if (write(fd,line2,strlen(line2)+1)==0)
    {
            printf("ok2\n");

    }
    return 0;
}

int readline(int fd,char* str)
{
    int n;

    do
    {
        n=read(fd,str,1);
    }
    while(n>0 && *str++ !=0);
     return(n>0);
}
int readrecipe(int fd)
{
    char str[200];
    while(readline(fd,str))
        printf("%s\n",str);
    return 0;
}

int main()
{

    int serverfd,clientfd;

    socklen_t serverlen,clientlen;
    struct sockaddr_un serveraddr;
    struct sockaddr_un clientaddr;

    struct sockaddr* serversockaddrptr;
    struct sockaddr* clientsockaddrptr;

    signal(SIGCHLD,SIG_IGN);
    serversockaddrptr=(struct sockaddr*) &serveraddr;
    serverlen=sizeof(serveraddr);

    clientsockaddrptr=(struct sockaddr*) &clientaddr;
    clientlen=sizeof(clientaddr);

    serverfd=socket(PF_LOCAL,SOCK_STREAM,DEFAULT_PROTOCOL);
    serveraddr.sun_family=PF_LOCAL;

    strcpy(serveraddr.sun_path,"recipe");
    bind(serverfd,serversockaddrptr,serverlen);

    listen(serverfd,5);

    while(1)
    {
        sleep(1);

            clientfd=accept(serverfd,clientsockaddrptr,&clientlen);
            if (clientfd>0)
            {
                printf("1\n");
                writerecipe(clientfd);
                close(clientfd);
                exit(0);


            }
            else
            {
                printf("nok1\n");
            }
      }
      return 0;
}
but still get this:
Quote:
nok1
nok1
nok1
nok1
nok1
nok1
nok1
nok1
nok1
.
.
.
thanks for any help.
 
Old 12-13-2011, 02:58 AM   #5
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,862
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
You are allowed to check for errors (and report them). Example:

Code:
@@ -1 +1,2 @@
+#include <errno.h>
 #include <stdio.h>
@@ -50,3 +51,3 @@
 {
-
+    int rc, ern;
     int serverfd,clientfd;
@@ -71,3 +72,10 @@
     strcpy(serveraddr.sun_path,"recipe");
-    bind(serverfd,serversockaddrptr,serverlen);
+    rc= bind(serverfd,serversockaddrptr,serverlen);
+    if (rc) {
+       ern= errno;
+
+        fprintf (stderr, "bind error %d: %s\n",
+                ern, strerror (errno));
+       return 5;
+    }
 
@@ -91,3 +99,7 @@
             {
-                printf("nok1\n");
+               ern= errno;
+
+                fprintf (stderr, "accept error %d: %s\n",
+                        ern, strerror (errno));
+               return 4;
             }
 
Old 12-13-2011, 06:16 AM   #6
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by golden_boy615 View Post
thanks for your reply my problem is that accept call does not wait for connection and it returns with failure and prints:

so I putted sleep in that to preventing fast while busy waiting .
and I deleted the fork and client section but the problem still exist:
Code:
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>

#define DEFAULT_PROTOCOL 0

int writerecipe(int fd)
{
    static char* line1 = "spam spam ,spam,spam,";
    static char* line2 = "2spam 2spam ,2spam,2spam.";

    if (write(fd,line1,strlen(line1)+1)==0)
    {
            printf("ok1\n");

    }
    if (write(fd,line2,strlen(line2)+1)==0)
    {
            printf("ok2\n");

    }
    return 0;
}

int readline(int fd,char* str)
{
    int n;

    do
    {
        n=read(fd,str,1);
    }
    while(n>0 && *str++ !=0);
     return(n>0);
}
int readrecipe(int fd)
{
    char str[200];
    while(readline(fd,str))
        printf("%s\n",str);
    return 0;
}

int main()
{

    int serverfd,clientfd;

    socklen_t serverlen,clientlen;
    struct sockaddr_un serveraddr;
    struct sockaddr_un clientaddr;

    struct sockaddr* serversockaddrptr;
    struct sockaddr* clientsockaddrptr;

    signal(SIGCHLD,SIG_IGN);
    serversockaddrptr=(struct sockaddr*) &serveraddr;
    serverlen=sizeof(serveraddr);

    clientsockaddrptr=(struct sockaddr*) &clientaddr;
    clientlen=sizeof(clientaddr);

    serverfd=socket(PF_LOCAL,SOCK_STREAM,DEFAULT_PROTOCOL);
    serveraddr.sun_family=PF_LOCAL;

    strcpy(serveraddr.sun_path,"recipe");
    bind(serverfd,serversockaddrptr,serverlen);

    listen(serverfd,5);

    while(1)
    {
        sleep(1);

            clientfd=accept(serverfd,clientsockaddrptr,&clientlen);
            if (clientfd>0)
            {
                printf("1\n");
                writerecipe(clientfd);
                close(clientfd);
                exit(0);


            }
            else
            {
                printf("nok1\n");
            }
      }
      return 0;
}
but still get this:

thanks for any help.
I added an include for string.h in the code above (because it is needed), compiled it (using gcc -Wall -pedantic), and then ran it.

As expected, the Unix (Local) socket was created in the current directory with the name of "recipe". When I launched a separate client (one of my own) to connect to that socket, my client received the following messages (w/o a newline): Server Response: spam spam ,spam,spam,

My client didn't bother to check for additional messages, but I'm sure if it did, it would have received the hard-coded message associated with the variable "line2".

As for the server, it only outputted the following uninformative message: 1

Anyhow, from what I could tell, the server application "works". You still have an issue in writerecipe(); as I mentioned earlier (and it seems that you ignored this advice), write() returns the number of bytes written. If you merely check for equality to zero, and then print a message indicating "ok", then you are misleading yourself. How about something like this:
Code:
    size_t line1_len = strlen(line1);
    int    bytes_written = 0;

    while (bytes_written != line1_len)
    {
        int result = write(fd, line1 + bytes_written, line1_len - bytes_written);

        if (result < 0)
        {
           if (errno == EWOULDBLOCK || errno == EINTR)
              continue;

           perror("write failed");
           break;
        }

        bytes_written += result;
    }
You are not required to write a null byte.

Last edited by dwhitney67; 12-13-2011 at 06:22 AM.
 
Old 12-13-2011, 01:46 PM   #7
golden_boy615
Member
 
Registered: Dec 2008
Distribution: Ubuntu Fedora
Posts: 445

Original Poster
Rep: Reputation: 18
thanks for reply I changed what you said about write and I found something that when I start the program for the first time that socket file recipe does not exist it is working !!! but with strange message 1 that you said (this is my first question why) but the second question is when I start it for the second time or more which recipe file exist it does not work and accept system call failed and nok message start printing again.Any way I found that if the recipe file exist before it does not work but if I remove it and let the program to create it again it works fine except it prints 1 message that I don't know where it comes from?
my code is:
Code:
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#define DEFAULT_PROTOCOL 0

int writerecipe(int fd)
{
    static char* line1 = "spam spam ,spam,spam,";
    static char* line2 = "2spam 2spam ,2spam,2spam.";

    if (write(fd,line1,strlen(line1)+1)<0)
    {
            printf("ok1\n");

    }
    if (write(fd,line2,strlen(line2)+1)<0)
    {
            printf("ok2\n");

    }
    return 0;
}

int readline(int fd,char* str)
{
    int n;

    do
    {
        n=read(fd,str,1);
    }
    while(n>0 && *str++ !=0);
     return(n>0);
}
int readrecipe(int fd)
{
    char str[200];
    memset(str,0,sizeof(str));
    while(readline(fd,str))
        printf("%s\n",str);
    return 0;
}

int main()
{
    int serverfd,clientfd;

    socklen_t serverlen,clientlen;
    struct sockaddr_un serveraddr;
    struct sockaddr_un clientaddr;

    struct sockaddr* serversockaddrptr;
    struct sockaddr* clientsockaddrptr;

    signal(SIGCHLD,SIG_IGN);
    serversockaddrptr=(struct sockaddr*) &serveraddr;
    serverlen=sizeof(serveraddr);

    clientsockaddrptr=(struct sockaddr*) &clientaddr;
    clientlen=sizeof(clientaddr);

    serverfd=socket(PF_LOCAL,SOCK_STREAM,DEFAULT_PROTOCOL);
    serveraddr.sun_family=PF_LOCAL;

    strcpy(serveraddr.sun_path,"recipe");
    bind(serverfd,serversockaddrptr,serverlen);

    listen(serverfd,5);

    while(1)
    {
        sleep(1);
        if (fork()==0)
        {
            clientfd=accept(serverfd,clientsockaddrptr,&clientlen);
            if (clientfd>0)
            {
                printf("1\n");
                writerecipe(clientfd);
                close(clientfd);
                exit(0);


            }
            else
            {
                printf("nok1\n");
            }

        }
        else
        {
            int clientfd2,result;

            socklen_t serverlen2;
            struct sockaddr_un serveraddr2;

            struct sockaddr* serversockaddrptr2;

            serversockaddrptr2=(struct sockaddr*) &serveraddr2;
            serverlen2=sizeof(serveraddr2);

            clientfd2=socket(PF_LOCAL,SOCK_STREAM,DEFAULT_PROTOCOL);
            serveraddr2.sun_family=PF_LOCAL;

            strcpy(serveraddr2.sun_path,"recipe");
            do
            {
                result=connect(clientfd2,serversockaddrptr2,serverlen2);
                if(result==-1)
                sleep(2);
            }
            while(result==-1);

            readrecipe(clientfd2);
            close(clientfd2);
        }
    }
}
 
Old 12-14-2011, 02:18 AM   #8
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,862
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
if 'write' returns error, don't print "ok", print errno and strerror(errno)
 
  


Reply



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
Socket programming problem. sam1201 Programming 4 08-26-2009 12:40 AM
Socket Programming problem lucky6969b Programming 4 12-27-2005 12:44 AM
socket programming problem...??? arunka Programming 4 10-11-2005 08:08 AM
socket programming problem bgraur Programming 2 03-09-2003 09:05 AM
Socket programming problem krivi Programming 3 01-14-2002 02:04 AM

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

All times are GMT -5. The time now is 02:30 PM.

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