Advanced UNIX Programming Environment --TCP / IP network programming commonly used UNIX Network Information Retrieval function-level programming environment --TCP / IP network programming

Common network information retrieval function

gethostname()
 
getppername()
 
getsockname()
 
gethostbyname()
 
gethostbyaddr()
 
getprotobyname()
 
getprotobynumber()
 
getservbyname()
 
getservbyport()

Setting network properties

head File:
#include <sys/types.h>
#include <sys/socket.h> 
 
Get a socket option
int getsockopt(
              int sockfd,
              int level, //   option defines the level. Support levels only SOL_SOCKET and IPPROTO_TCP and IPPROTO_IP
              int optname, //   need to get socket option.
              void * optval, //   pointer to the buffer storage option values obtained.
              socklen_t * optlen //   pointer length value optval buffer.
              ); 
return value:   
No error: return 0.
Error: the error SOCKET_ERROR returned, the application can obtain the corresponding error code WSAGetLastError ().
 
Comment:   
a getsockopt () function is used to obtain any type, any state of the current value of the option sockets, and stores the result optval. Options exist at different protocol layers, but often at the highest "socket" level, setting options that affect the operation of the socket, such as a blocking operation or not, selected from the mode diameter of the package, and the like band data transmission. The selected value of the option on optval buffer. Number of points comprises shaping optlen in the initial length of the buffer, when the call returns the length is set to the actual value. SO_LINGER terms of options, equivalent to the size of the linger structure, other options, it is the size of an integer number. If not setsockopt () call, then getsockopt () returns the default value.
Set socket options
int setsockopt(
            int sockfd, // descriptor identifying a socket.
            int level, // option defines the hierarchy; currently only supports SOL_SOCKET and IPPROTO_TCP level.
            int optname, // options to be set.
            const void * optval, // pointer to the buffer storage option value.
            socklen_t optlen // optval buffer length.
            );
 
return value:
No error: return 0.
Error: the error SOCKET_ERROR returned, the application can obtain the corresponding error code WSAGetLastError ().
 
Comment:
setsockopt () function is used for any type, any state set option values ​​socket. Although there are options on the different protocol layers, but this function is only defined options on the highest "socket" level. Socket options affect operations, such as expedited data is received in the normal data stream, whether the broadcast data and the like can be transmitted from the interface units. There are two sets of interface options: One is the Boolean options, enable or disable a feature; the other is plastic or structural options. Allow a Boolean option, the optval points nonzero integers; prohibit an option optval points integers equal to zero. For boolean option, should be equal optlen sizeof (int); other options, the optval integers or structure points to a desired option, and compared with the length of integers or optlen structure. SO_LINGER options for controlling operations of the following cases: there are queued data to be sent on the socket, and the closesocket () call is performed.




IO system and server model

There are four main I / O models under unix / linux
  • Blocking I / O :( pipe size 64K)
Simple, low efficiency, the most commonly used
Read blocking
read,readv,recv,recvfrom,recvmsg
Not readable data buffer
Write obstruction
write,writev,send,sendmag
Write buffer is less than the amount of data to be written is smaller than (UDP exceptions, no concept of buffer)
other:
accept,connect

  • Non-blocking I / O:
Prevents the process blocked on I / O operations
If the requested I / O can not be completed immediately, an error is returned.
Is there a need to set non-blocking data cycle test file descriptor. (Poling) consuming CPU resources.
:( achieved using fcntl () function)
#include <unistd.h>
#include <fcntl.h>
 
int fcntl (int fd, // file descriptor
                int cmd, command // operation
                long arg // flock structure pointer
 
return value:
Successful return 0,
-1 error is returned, and set errno.
Example:
struct flcok
{
short int l_type;
short int l_whence;
off_t l_start;
off_t l_len;
pid_t l_pid;
}
l_type three states: 
F_RDLCK establish a lock used for reading
F_WRLCK establish a lock used for writing
Lock established before F_UNLCK deleted
l_whence there are three ways: 
SEEK_SET to the beginning of the file is locked starting position.
SEEK_CUR to read and write files currently locked position to the starting position
SEEK_END end of the file is locked to the starting position. 

  • I / O multiplexing:
Allows the simultaneous control of the plurality of I / O
 
thought:
  • Construction related to a file descriptor table;
  • Calling a function to obtain these returns a descriptor ready for I / O;
  • Upon return, which tell the descriptor of the process is ready, and can be I / O.

  • Drive signal I / O:
Asynchronous communication model

I / O multiplexing concurrent server process 


#include <sys/time.h>
#include <sys/types.h>
int select (int n, // monitoring of all file descriptors collection
                  fd_set * readfds, // set of all file descriptors to read
                  fd_set * writefds, // write the set of all file descriptors
                  fd_set * exceptfds, // file descriptor we want to inform the other
                  struct timeval * timeout) // timeout.
Optional parameters timeout: NULL: block until the file descriptor is ready or error, 0: only detects the state of the file descriptor sets, and then returns immediately, 0: For the specified time, if nothing happened, timeout returns.

When we call the process will select the file may have been blocked to read or write or files can be set to timeout.
 
Related to the macro file descriptor
void FD_SET (int fd, fd_set * fdset) // will be added to the FD fdset
void FD_CLR (int fd, fd_set * fdset) // fd will be removed from inside fdset
void FD_ZERO (fd_set * fdset) // remove all file descriptors from the fdset
void FD_ISSET (int fd, fd_set * fdset) // determines whether fd set fdset

#include <sys/poll.h>
int poll (struct pollfd * fds, // file descriptor
                unsigned int nfds, concerned events //
                int timeout )    //

Bottom:
 

//select_server1.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/time.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <errno.h>
#include <strings.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define N 64 
typedef struct sockaddr SA;

int main(int argc, char *argv[])
{
    int listenfd, connfd, maxfd, i;
    struct sockaddr_in servaddr, peeraddr;
    socklen_t len;
    char buf[N] = {0};
    fd_set rdfs, bakrdfs;
    ssize_t n;

    if (argc < 3)
    {
        fprintf(stdout, "usage:%s <ip> <port>\n", argv[0]);
        exit(0);
    }

    bzero(&servaddr, sizeof(servaddr));

    if ((listenfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket");
        exit(-1);
    }

    servaddr.sin_family = PF_INET;
    servaddr.sin_port = htons(atoi(argv[2]));
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);

    if (bind(listenfd, (SA *)&servaddr, sizeof(servaddr)) == -1)  
    {       
        perror("bind");
        exit(-1);
    }

    listen(listenfd, 5);
    maxfd = listenfd;

    FD_ZERO(&bakrdfs);
    FD_SET(listenfd, &bakrdfs);

    len = sizeof(peeraddr);
    while (1)
    {
        rdfs = bakrdfs;

        if (select(maxfd+1, &rdfs, NULL, NULL, NULL) == -1)
        {
            perror("select");
            exit(-1);
        }

        for (i = 0; i <= maxfd; i++)
        {
            if (FD_ISSET(i, &rdfs))
            {
                if (i == listenfd)
                {
                    if ((connfd = accept(i, (SA *)&peeraddr, &len)) == -1)
                    {
                        perror("accept");
                        exit(-1);
                    }
                    fprintf(stdout, "welcome %s %d\n", 
                            inet_ntoa(peeraddr.sin_addr), 
                            ntohs(peeraddr.sin_port));

                    FD_SET(connfd, &bakrdfs);
                    maxfd = (maxfd > connfd) ? maxfd : connfd;
                }
                else
                {
                    bzero(buf, sizeof(buf));
                    if ((n = recv(i, buf, N, 0)) == 0)
                    {
                        close(i);
                        FD_CLR(i, &bakrdfs);
                    }
                    else
                    {
                        printf("n=%d %s\n", n, buf);
                        send(i, buf, N, 0);
                    }
                }
            }
        }
    }

    exit(0);
}

//select_server2.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/time.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <errno.h>
#include <strings.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define N 64 
typedef struct sockaddr SA;

int main(int argc, char *argv[])
{
    int listenfd, connfd, maxfd, i;
    struct sockaddr_in servaddr, peeraddr;
    socklen_t len;
    char buf[N] = {0};
    fd_set rdfs;

    if (argc < 3)
    {
        fprintf(stdout, "usage:%s <ip> <port>\n", argv[0]);
        exit(0);
    }

    bzero(&servaddr, sizeof(servaddr));

    if ((listenfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket");
        exit(-1);
    }

    servaddr.sin_family = PF_INET;
    servaddr.sin_port = htons(atoi(argv[2]));
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);

    if (bind(listenfd, (SA *)&servaddr, sizeof(servaddr)) == -1)  
    {       
        perror("bind");
        exit(-1);
    }

    listen(listenfd, 5);
    maxfd = listenfd;

    FD_ZERO(&rdfs);
    while (1)
    {
        FD_SET(0, &rdfs);
        FD_SET(listenfd, &rdfs);
        if (select(maxfd+1, &rdfs, NULL, NULL, NULL) == -1)
        {
            perror("select");
            exit(-1);
        }

        for (i = 0; i <= maxfd; i++)
        {
            if (FD_ISSET(i, &rdfs))
            {
                if (i == 0)
                {
                    fgets(buf, N, stdin);
                    printf("*************\n");
                    printf("%s", buf);
                }
                else if (i == listenfd)
                {
                    len = sizeof(peeraddr);
                    if ((connfd = accept(listenfd, (SA *)&peeraddr, &len)) == -1)
                    {
                        perror("accept");
                        exit(-1);
                    }
                    fprintf(stdout, "welcome %s %d\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port));
                    close(connfd);
                }
            }
        }
    }

    exit(0);
}

//client.c
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <strings.h>
#include <netinet/in.h>
#include <arpa/inet.h>

typedef struct sockaddr SA;
#define N 64

int main(int argc, char *argv[])
{
    int sockfd;
    ssize_t n;
    struct sockaddr_in servaddr;
    char buf[N] = {0};

    if (argc < 3)
    {
        fprintf(stdout, "usage:%s ip port\n", argv[0]);
        exit(0);
    }

    if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket");
        exit(-1);
    }
    
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = PF_INET;
    servaddr.sin_port = htons(atoi(argv[2]));// "9000"---9000
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);

    if (connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) == -1)
    {
        perror("connect");
        exit(-1);
    }

    printf(">");
    while (fgets(buf, N, stdin) != NULL)//abc\n 
    {
        buf[strlen(buf)-1] = 0;//abc\0
        send(sockfd, buf, N, 0);

        bzero(buf, sizeof(buf));
        n = recv(sockfd, buf, N, 0);
        printf("n=%d buf=%s\n", n, buf);
        printf(">");
    }

    close(sockfd);

    exit(0);
}


network timeout:

The need to detect timeout:
  • Avoid unlimited data without blocking
  • When the set time, the return process continues to run from the original operation

TCP sockets in recv / accept / connect
The UDP socket recvfrom
Will cause obstruction

Timeout three methods of detection:

1, set the properties of SO_RCVTIMEO socket
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <strings.h>
#include <netinet/in.h>
#include <arpa/inet.h>

typedef struct sockaddr SA;

voidf(int sig) {printf("*\n");}

int main(int argc, char *argv[])
{
    int listenfd, connfd;
    struct sockaddr_in myaddr, peeraddr;
    socklen_t len;

    if (argc < 3)
    {
        fprintf(stdout, "usage:%s ip port\n", argv[0]);
        exit(0);
    }

    if ((listenfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket");
        exit(-1);
    }
    
    bzero(&myaddr, sizeof(myaddr));
    myaddr.sin_family = PF_INET;
    myaddr.sin_port = htons(atoi(argv[2]));//htons(9000)
    myaddr.sin_addr.s_addr = inet_addr(argv[1]);

    int on = 1;
    if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
    {
        perror("setsockopt");
        exit(-1);
    }

    if (bind (listenfd, (SA *)&myaddr, sizeof(myaddr)) == -1)
    {
        perror("bind");
        exit(-1);
    }

    if (listen(listenfd, 5) == -1)
    {
        perror("listen");
        exit(-1);
    }

    bzero(&peeraddr, sizeof(peeraddr));
    len = sizeof(peeraddr);

    struct timeval t={5, 0};

    if (setsockopt(listenfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t)) == -1)
    {
        perror("setsockopt");
        exit(-1);
    }

    while (1)
    {
        if ((connfd = accept(listenfd, (SA *)&peeraddr, &len)) == -1)
        {
            printf("%d\n", errno);
            exit(-1);
        }
        printf("welcome %s:%d\n", inet_ntoa(peeraddr.sin_addr),
                ntohs(peeraddr.sin_port));

        close(connfd);
    }


    exit(0);
}

2, with select whether the ready detection socket 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/time.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <errno.h>
#include <strings.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define N 64 
typedef struct sockaddr SA;

int main(int argc, char *argv[])
{
    int listenfd, connfd, maxfd, i;
    struct sockaddr_in servaddr, peeraddr;
    socklen_t len;
    char buf[N] = {0};
    fd_set rdfs;

    if (argc < 3)
    {
        fprintf(stdout, "usage:%s <ip> <port>\n", argv[0]);
        exit(0);
    }

    bzero(&servaddr, sizeof(servaddr));

    if ((listenfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket");
        exit(-1);
    }

    servaddr.sin_family = PF_INET;
    servaddr.sin_port = htons(atoi(argv[2]));
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);

    if (bind(listenfd, (SA *)&servaddr, sizeof(servaddr)) == -1)  
    {       
        perror("bind");
        exit(-1);
    }

    listen(listenfd, 5);
    maxfd = listenfd;

    int n;

    FD_ZERO(&rdfs);
    while (1)
    {
        struct timeval t = {5, 0};
        FD_SET(0, &rdfs);
        FD_SET(listenfd, &rdfs);
        if ((n = select(maxfd+1, &rdfs, NULL, NULL, &t)) == -1)
        {
            perror("select");
            exit(-1);
        }
        printf("n=%d\n", n);

        for (i = 0; i <= maxfd; i++)
        {
            if (FD_ISSET(i, &rdfs))
            {
                if (i == 0)
                {
                    fgets(buf, N, stdin);
                    printf("*************\n");
                    printf("%s", buf);
                }
                else if (i == listenfd)
                {
                    len = sizeof(peeraddr);
                    if ((connfd = accept(listenfd, (SA *)&peeraddr, &len)) == -1)
                    {
                        perror("accept");
                        exit(-1);
                    }
                    fprintf(stdout, "welcome %s %d\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port));
                    close(connfd);
                }
            }
        }
    }

    exit(0);
}


3, sets a timer (Timer), the signal captured SIGALRMI 
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <strings.h>
#include <netinet/in.h>
#include <arpa/inet.h>

typedef struct sockaddr SA;

void f(int sig) 
{
    printf("signo=%d\n", sig);
    alarm(5);
}

int main(int argc, char *argv[])
{
    int listenfd, connfd;
    struct sockaddr_in myaddr, peeraddr;
    socklen_t len;

    if (argc < 3)
    {
        fprintf(stdout, "usage:%s ip port\n", argv[0]);
        exit(0);
    }

    if ((listenfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket");
        exit(-1);
    }
    
    bzero(&myaddr, sizeof(myaddr));
    myaddr.sin_family = PF_INET;
    myaddr.sin_port = htons(atoi(argv[2]));//htons(9000)
    myaddr.sin_addr.s_addr = inet_addr(argv[1]);

    if (bind (listenfd, (SA *)&myaddr, sizeof(myaddr)) == -1)
    {
        perror("bind");
        exit(-1);
    }

    if (listen(listenfd, 5) == -1)
    {
        perror("listen");
        exit(-1);
    }

    bzero(&peeraddr, sizeof(peeraddr));
    len = sizeof (peeraddr);

//    signal(SIGALRM, f);
    struct sigaction act;

    sigaction(SIGALRM, NULL, &act);
    act.sa_handler = f;
    sigaction(SIGALRM, &act, NULL);

    printf("**\n");
    while (1)
    {
        alarm(5);
        if ((connfd = accept(listenfd, (SA *)&peeraddr, &len)) == -1)
        {
            printf("%d\n", errno);
            exit(-1);
        }
        printf("welcome %s:%d\n", inet_ntoa(peeraddr.sin_addr),
                ntohs(peeraddr.sin_port));


        close(connfd);
    }


    exit(0);
}


broadcast

Only Datagram (UDP protocol) to be able to broadcast
MAC: FF: FF: FF: FF: FF: FF

The sender
  • Create a User Datagram Sockets
  • Socket does not allow broadcast packets created by default, need to set the property
  • Recipient address as a broadcast address
  • Information specified port
  • Transmission packet

Process


 
Receiving end
  • Create a User Datagram Sockets
  • Bound local IP address and port (the same port binding must specify the sender port)
  • Waiting to receive data

Process
 



//receiver.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <strings.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>

typedef struct sockaddr SA;
#define N 64

int main(int argc, char *argv[])
{
    int sockfd;
    struct sockaddr_in myaddr, peeraddr;
    socklen_t len;
    char buf[N] = {0};

    if (argc < 3)
    {
        fprintf(stdout, "usage:%s ip port\n", argv[0]);
        exit(0);
    }

    if ((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
    {
        perror("socket");
        exit(-1);
    }
    
    bzero(&myaddr, sizeof(myaddr));
    myaddr.sin_family = PF_INET;
    myaddr.sin_port = htons(atoi(argv[2]));//6000
    myaddr.sin_addr.s_addr = inet_addr(argv[1]);//0.0.0.0 192.168.1.255

    if (bind (sockfd, (SA *)&myaddr, sizeof(myaddr)) == -1)
    {
        perror("bind");
        exit(-1);
    }

    len = sizeof(peeraddr);
    bzero(&peeraddr, sizeof(peeraddr));

    while (1)
    {
        bzero(buf, sizeof(buf));
        if (-1 == recvfrom(sockfd, buf, N, 0, (SA *)&peeraddr, &len))
        {
            printf("errno=%d %s\n", errno, strerror(errno));
            exit(-1);
        }

        printf("from %s:%d %s\n", inet_ntoa(peeraddr.sin_addr),
                ntohs(peeraddr.sin_port), buf);
    }

    exit(0);
}
 
//sender.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <strings.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>

typedef struct sockaddr SA;
#define N 64

int main(int argc, char *argv[])
{
    int sockfd;
    struct sockaddr_in servaddr;
    char buf[N] = {0};

    if (argc < 3)
    {
        fprintf(stdout, "usage:%s ip port\n", argv[0]);
        exit(0);
    }

    if ((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
    {
        perror("socket");
        exit(-1);
    }

    int on = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) == -1)
    {
        perror("setsockopt");
        exit(-1);
    }
    
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = PF_INET;
    servaddr.sin_port = htons(atoi(argv[2]));// 6000
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);//192.168.1.255

    strcpy(buf, "this is a broadcast package");
    while (1)
    {
        sendto(sockfd, buf, N, 0, (SA *)&servaddr, sizeof(servaddr));
        sleep(1);
    }

    close(sockfd);

    exit(0);
}

Multicast

Multicast address: 224.10.10.1
MAC:01:00:5E:0A:0A:01

Multicast transmissions:
  • Create a User Datagram Sockets
  • Recipient address is a multicast address designated
  • Information specified port
  • Transmission packet

Multicast reception
  • Create a User Datagram Sockets
  • Join a multicast group
  • Bound local IP address and port (port binding must be the same sender and the specified port)
  • Waiting to receive data

//sender.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <strings.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>

typedef struct sockaddr SA;
#define N 64

int main(int argc, char *argv[])
{
    int sockfd;
    struct sockaddr_in servaddr;
    char buf[N] = {0};

    if (argc < 3)
    {
        fprintf(stdout, "usage:%s ip port\n", argv[0]);
        exit(0);
    }

    if ((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
    {
        perror("socket");
        exit(-1);
    }

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = PF_INET;
    servaddr.sin_port = htons(atoi(argv[2]));// 6000
    servaddr.sin_addr.s_addr = inet_addr(argv[1]);//224.10.10.1

    strcpy(buf, "this is a multicast package");
    while (1)
    {
        sendto(sockfd, buf, N, 0, (SA *)&servaddr, sizeof(servaddr));
        sleep(1);
    }

    close(sockfd);

    exit(0);
}
 
//receiver.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <strings.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>

typedef struct sockaddr SA;
#define N 64

int main(int argc, char *argv[])
{
    int sockfd;
    struct sockaddr_in myaddr, peeraddr;
    socklen_t len;
    char buf[N] = {0};
    struct ip_mreq mreq;

    if (argc < 3)
    {
        fprintf(stdout, "usage:%s ip port\n", argv[0]);
        exit(0);
    }

    if ((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
    {
        perror("socket");
        exit(-1);
    }

    bzero(&mreq, sizeof(mreq));
    mreq.imr_multiaddr.s_addr = inet_addr("224.10.10.1");
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);

    if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1)
    {
        perror("setsockopt");
        exit(-1);
    }
    
    bzero(&myaddr, sizeof(myaddr));
    myaddr.sin_family = PF_INET;
    myaddr.sin_port = htons(atoi(argv[2]));//6000
    myaddr.sin_addr.s_addr = inet_addr(argv[1]);//0.0.0.0 224.10.10.1

    if (bind (sockfd, (SA *)&myaddr, sizeof(myaddr)) == -1)
    {
        perror("bind");
        exit(-1);
    }

    len = sizeof(peeraddr);
    bzero(&peeraddr, sizeof(peeraddr));

    while (1)
    {
        bzero(buf, sizeof(buf));
        if (-1 == recvfrom(sockfd, buf, N, 0, (SA *)&peeraddr, &len))
        {
            printf("errno=%d %s\n", errno, strerror(errno));
            exit(-1);
        }

        printf("from %s:%d %s\n", inet_ntoa(peeraddr.sin_addr),
                ntohs(peeraddr.sin_port), buf);
    }

    exit(0);
}


setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq);



                                     

                                     



UNIX domain sockets

Features: 
  • Commonly used in the foreground and local interprocess communication
  • Create a socket using native protocols PF_UNIX (or PF_LOCAL)
  • Into stream sockets and user datagram sockets
  • Compared to other process communication methods are easy to use, and high efficiency

Local address of the structure:

struct sockaddr_un    //<sys/un.h>
{
        sa_family_t sun_family;
        char sun_path [108]; // socket file path
}
use:
struct sockaddr_un myaddr;
bzero(&myaddr,sizeof(myaddr));
 
myaddr.sun_family = PF_UNIX;
strcpy(myaddr.sun_path,"mysocket");

UNIX domain (stream) socket

Server
  • socker(PF_UNIX,SOCK_STREAM,0)
  • bind (, local address)
  • listen(,)
  • accept(,,)
  • recv()/send()
  • ……

Client
  • socker(PF_UNIX,SOCK_STREAM,0)
  • bind (, local address) // optional
  • connect(, , )
  • recv()/send()
  • ……

//server.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <strings.h>
#include <sys/un.h>

typedef struct sockaddr SA;
#define N 64


int main(int argc, char *argv[])
{
    int listenfd, connfd;
    struct sockaddr_un myaddr, peeraddr;
    socklen_t len;
    char buf[N] = {0};
    ssize_t n;


    if ((listenfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
    {
        perror("socket");
        exit(-1);
    }
    
    bzero(&myaddr, sizeof(myaddr));
    myaddr.sun_family = PF_UNIX;
    strcpy(myaddr.sun_path, "serversocket");

    unlink("serversocket");
    if (bind (listenfd, (SA *)&myaddr, sizeof(myaddr)) == -1)
    {
        perror("bind");
        exit(-1);
    }

    if (listen(listenfd, 5) == -1)
    {
        perror("listen");
        exit(-1);
    }

    bzero(&peeraddr, sizeof(peeraddr));
    len = sizeof(peeraddr);

    while (1)
    {
        if ((connfd = accept(listenfd, (SA *)&peeraddr, &len)) == -1)
        {
            perror("accept");
            exit(-1);
        }
        printf("welcome %s\n", peeraddr.sun_path);

        while (1)
        {
            bzero(buf, sizeof(buf));
            if ((n = recv(connfd, buf, N, 0)) == 0)
                break;
            send(connfd, buf, N, 0);
        }

        close(connfd);
    }


    exit(0);
}
//client.c
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <strings.h>
#include <sys/un.h>

typedef struct sockaddr SA;
#define N 64

int main(int argc, char *argv[])
{
    int sockfd;
    ssize_t n;
    struct sockaddr_un servaddr,myaddr;
    char buf[N] = {0};

    if ((sockfd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
    {
        perror("socket");
        exit(-1);
    }

#if 1
    bzero(&myaddr, sizeof(myaddr));
    myaddr.sun_family = PF_UNIX;
    strcpy(myaddr.sun_path, "clientsocket");

    unlink("clientsocket");
    if (bind (sockfd, (SA *)&myaddr, sizeof(myaddr)) == -1)
    {
        perror("bind");
        exit(-1);
    }
#endif
    
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sun_family = PF_UNIX;
    strcpy(servaddr.sun_path, "serversocket");

    if (connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) == -1)
    {
        perror("connect");
        exit(-1);
    }

    printf(">");
    while (fgets(buf, N, stdin) != NULL)//abc\n 
    {
        buf[strlen(buf)-1] = 0;//abc\0
        send(sockfd, buf, N, 0);

        bzero(buf, sizeof(buf));
        n = recv(sockfd, buf, N, 0);
        printf("n=%d buf=%s\n", n, buf);
        printf(">");
    }

    close(sockfd);

    exit(0);
}


UNIX domain (user datagram) socket

 


//client.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <strings.h>
#include <string.h>
#include <sys/un.h>

typedef struct sockaddr SA;
#define N 64

int main(int argc, char *argv[])
{
    int sockfd;
    struct sockaddr_un servaddr, myaddr;
    socklen_t len;
    char buf[N] = {0};

    if ((sockfd = socket(PF_UNIX, SOCK_DGRAM, 0)) == -1)
    {
        perror("socket");
        exit(-1);
    }
    
    bzero(&myaddr, sizeof(myaddr));
    myaddr.sun_family = PF_UNIX;
    strcpy(myaddr.sun_path, "clientsocket");

    unlink("clientsocket");
    if (bind (sockfd, (SA *)&myaddr, sizeof(myaddr)) == -1)
    {
        perror("bind");
        exit(-1);
    }

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sun_family = PF_UNIX;
    strcpy(servaddr.sun_path, "serversocket");

    printf(">");
    while (fgets(buf, N, stdin) != NULL)
    {
        buf[strlen(buf)-1] = 0;
        sendto(sockfd, buf, N, 0, (SA *)&servaddr, sizeof(servaddr));
        bzero(buf, sizeof(buf));
        recvfrom(sockfd, buf, N, 0, NULL, NULL);
        printf("%s\n", buf);
        printf(">");
    }

    close(sockfd);

    exit(0);
}
//server.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <strings.h>
#include <string.h>
#include <sys/un.h>

typedef struct sockaddr SA;
#define N 64

int main(int argc, char *argv[])
{
    int sockfd;
    struct sockaddr_un myaddr, peeraddr;
    socklen_t len;
    char buf[N] = {0};

    if ((sockfd = socket(PF_UNIX, SOCK_DGRAM, 0)) == -1)
    {
        perror("socket");
        exit(-1);
    }
    
    bzero(&myaddr, sizeof(myaddr));
    myaddr.sun_family = PF_UNIX;
    strcpy(myaddr.sun_path, "serversocket");

    unlink("serversocket");
    if (bind (sockfd, (SA *)&myaddr, sizeof(myaddr)) == -1)
    {
        perror("bind");
        exit(-1);
    }

    len = sizeof(peeraddr);
    bzero(&peeraddr, sizeof(peeraddr));

    while (1)
    {
        bzero(buf, sizeof(buf));
        if (-1 == recvfrom(sockfd, buf, N, 0, (SA *)&peeraddr, &len))
        {
            printf("errno=%d %s\n", errno, strerror(errno));
            exit(-1);
        }

        printf("from %s: %s\n", peeraddr.sun_path, buf); 
        sendto(sockfd, buf, N, 0,(SA *) & peeraddr, sizeof (peeraddr));
    }

    exit(0);
}

 

 

Guess you like

Origin www.cnblogs.com/xinxihua/p/12563853.html