UNP函数笔记六: 基本UDP套接字编程

58 篇文章 0 订阅
49 篇文章 0 订阅

第八章  基本UDP套接字编程:

#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void * buff, size_t nbytes, int flags, 
                 struct sockaddr * from, socklen_t * addrlen);
    success return read-bytes(0 means recv a empty package), error return -1
    so it is different from tcp-read/recv(0 means get FIN)
    since it can use by tcp socket
ssize_t sendto(int sockfd, const void * buff, size_t nbytes, in flags, 
               const struct sockaddr * to, socklen_t addrlen);
    success return write-bytes, error return -1
    we can send a empty package(0 bytes)
    it can use by tcp socket

示例:

#ifndef __ERROR_EXIT_H__
#define __ERROR_EXIT_H__


#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

void err_exit(const char * msg)
{
    printf("%s: %s\n", msg, strerror(errno));
    exit(1);
}


#endif

#include <netinet/in.h>
#include <sys/socket.h>

#include "dg_echo.h"
#include "err_exit.h"

#define SERV_PORT 34567

int 
main(int argc, char * argv[])
{
    int                 sockfd;
    struct sockaddr_in  servaddr;
    struct sockaddr_in  cliaddr;

    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
        err_exit("socket error");
    }

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family      = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port        = htons(SERV_PORT);

    if (bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
        err_exit("bind error");
    }

    dg_echo(sockfd, (struct sockaddr *)&cliaddr, sizeof(cliaddr));
}

#include <netinet/in.h>
#include <sys/socket.h>

#include "err_exit.h"

#define MAXLINE 4096

void 
dg_echo(int sockfd, struct sockaddr * pcliaddr, socklen_t clilen)
{
    int        n;
    socklen_t  len;
    char       mesg[MAXLINE];

    for ( ; ; ) {
        len = clilen;
        if ((n = recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len)) == -1) {
            err_exit("recvfrom error");
        }

        if (sendto(sockfd, mesg, n, 0, pcliaddr, len) == -1) {
            err_exit("sendto error");
        }
    }
}

#include <netinet/in.h>
#include <sys/socket.h>

#include "dg_cli.h"
#include "err_exit.h"

#define SERV_PORT 34567

int 
main(int argc, char * argv[])
{
    int                 sockfd;
    struct sockaddr_in  servaddr;

    if (argc != 2) {
        printf("usage: udpcli <IPaddress>\n");
        exit(1);
    }

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERV_PORT);
    if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {
        err_exit("inet_pton error");
    }

    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
        err_exit("socket error");
    }

    dg_cli(stdin, sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

    exit(0);
}

#include <netinet/in.h>
#include <sys/socket.h>

#include "err_exit.h"

#define MAXLINE 4096

void 
dg_cli(FILE * fp, int sockfd, const struct sockaddr * pservaddr, 
       socklen_t servlen)
{
    int   n;
    char  sendline[MAXLINE];
    char  recvline[MAXLINE + 1];

    while (fgets(sendline, MAXLINE, fp) != NULL) {
        if (sendto(sockfd, sendline, strlen(sendline), 
                   0, pservaddr, servlen) == -1) {
            err_exit("sendto error");
        }

        if ((n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL)) == -1) {
            err_exit("recvfrom error");
        }

        recvline[n] = 0;  /* null terminate */
        if (fputs(recvline, stdout) == EOF) {
            err_exit("fputs error");
        }
    }
}

#include <netinet/in.h>
#include <sys/socket.h>

#include "err_exit.h"
#include "sock_ntop.h"

#define MAXLINE 4096

void 
dg_cli(FILE * fp, int sockfd, const struct sockaddr * pservaddr, 
       socklen_t servlen)
{
    int               n;
    char              sendline[MAXLINE];
    char              recvline[MAXLINE + 1];
    char            * paddr;
    socklen_t         len;
    struct sockaddr * preply_addr;

    if ((preply_addr = malloc(servlen)) == NULL) {
        err_exit("malloc error");
    }

    while (fgets(sendline, MAXLINE, fp) != NULL) {
        if (sendto(sockfd, sendline, strlen(sendline), 
                   0, pservaddr, servlen) == -1) {
            err_exit("sendto error");
        }

        len = servlen;
        if ((n = recvfrom(sockfd, recvline, MAXLINE, 
                          0, preply_addr, &len)) == -1) {
            err_exit("recvfrom error");
        }

        /*
         * it is not a good idea to use "memcmp"
         * cause may sendto-remote-ip and recvfrom-remote-ip is different
         * but they are in a same machine
         * so we may drop a right response
         */
        if (len != servlen || memcmp(pservaddr, preply_addr, len) != 0) {
            if ((paddr = sock_ntop(preply_addr, len)) == NULL) {
                err_exit("sock_ntop error");
            }
            printf("reply from %s (ignored)\n", paddr);
            continue;
        }

        recvline[n] = 0;  /* null terminate */
        if (fputs(recvline, stdout) == EOF) {
            err_exit("fputs error");
        }
    }
}

#include <netinet/in.h>
#include <sys/socket.h>

#include "err_exit.h"

#define MAXLINE 4096

void 
dg_cli(FILE * fp, int sockfd, const struct sockaddr * pservaddr, 
       socklen_t servlen)
{
    int   n;
    char  sendline[MAXLINE];
    char  recvline[MAXLINE + 1];

    if (connect(sockfd, (struct sockaddr *)pservaddr, servlen) == -1) {
        err_exit("connect error");
    }

    while (fgets(sendline, MAXLINE, fp) != NULL) {
        if (write(sockfd, sendline, strlen(sendline)) == -1) {
            err_exit("write error");
        }

        if ((n = read(sockfd, recvline, MAXLINE)) == -1) {
            err_exit("read error");
        }

        recvline[n] = 0;  /* null terminate */
        if (fputs(recvline, stdout) == EOF) {
            err_exit("fputs error");
        }
    }
}

#include <netinet/in.h>
#include <sys/socket.h>

#include "err_exit.h"

#define NDG   2000  /* datagrams to send */
#define DGLEN 1400  /* length of each datagram */

void
dg_cli(FILE * fp, int sockfd, const struct sockaddr * pservaddr, 
       socklen_t servlen)
{
    int   i;
    char  sendline[DGLEN];

    for (i = 0; i < NDG; i++) {
        if (sendto(sockfd, sendline, DGLEN, 0, pservaddr, servlen) == -1) {
            err_exit("sendto error");
        }
    }
}

#include <netinet/in.h>
#include <sys/socket.h>

#include "err_exit.h"
#include "my_signal.h"

#define MAXLINE 4096

int  count;

void 
recvfrom_int(int signo)
{
    printf("\nreceived %d datagrams\n", count);
    exit(0);
}

void 
dg_echo(int sockfd, struct sockaddr * pcliaddr, socklen_t clilen)
{
    socklen_t  len;
    char       mesg[MAXLINE];

    if (my_signal(SIGINT, recvfrom_int) == SIG_ERR) {
        err_exit("my_signal error");
    }

    for ( ; ; ) {
        len = clilen;
        if (recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len) == -1) {
            err_exit("recvfrom error");
        }

        count++;
    }
}

#include <netinet/in.h>
#include <sys/socket.h>

#include "err_exit.h"
#include "my_signal.h"

#define MAXLINE 4096

int  count;

void 
recvfrom_int(int signo)
{
    printf("\nreceived %d datagrams\n", count);
    exit(0);
}

void 
dg_echo(int sockfd, struct sockaddr * pcliaddr, socklen_t clilen)
{
    int        n;
    socklen_t  len;
    char       mesg[MAXLINE];

    if (my_signal(SIGINT, recvfrom_int) == SIG_ERR) {
        err_exit("my_signal error");
    }

    n = 220 * 1024;
    if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) == -1) {
        err_exit("setsockopt error");
    }

    for ( ; ; ) {
        len = clilen;
        if (recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, &len) == -1) {
            err_exit("recvfrom error");
        }

        count++;
    }
}

#include <netinet/in.h>
#include <sys/socket.h>

#include "err_exit.h"
#include "sock_ntop.h"

#define SERV_PORT 34567

int 
main(int argc, char * argv[])
{
    int                  sockfd;
    char               * paddr;
    socklen_t            len;
    struct sockaddr_in   cliaddr;
    struct sockaddr_in   servaddr;

    if (argc != 2) {
        printf("usage: udpcli <IPaddress>\n");
        exit(0);
    }

    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
        err_exit("socket error");
    }

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERV_PORT);
    if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {
        err_exit("inet_pton error");
    }

    if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
        err_exit("connect error");
    }

    len = sizeof(cliaddr);
    if (getsockname(sockfd, (struct sockaddr *)&cliaddr, &len) == -1) {
        err_exit("getsockname error");
    }
    if ((paddr = sock_ntop((struct sockaddr *)&cliaddr, len)) == NULL) {
        err_exit("sock_ntop error");
    }
    printf("local address %s\n", paddr);

    exit(0);
}

#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/wait.h>

#include "str_echo.h"
#include "err_exit.h"
#include "my_signal.h"

#define LISTENQ   1024
#define SERV_PORT 34567

#define max(a, b)  ((a) >= (b) ? (a) : (b))

void 
sig_chld(int signo)
{
    pid_t  pid;
    int    stat;

    while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) {  /* waitpid + WNOHANG */
        printf("child %d terminated\n", pid);
    }
    return;
}

int 
main(int argc, char * argv[])
{
    int                 listenfd;
    int                 connfd;
    int                 udpfd;
    int                 nready;
    int                 maxfdp1;
    char                mesg[MAXLINE];
    pid_t               childpid;
    fd_set              rset;
    ssize_t             n;
    socklen_t           len;
    const int           on = 1;
    struct sockaddr_in  cliaddr;
    struct sockaddr_in  servaddr;

    /* create listening TCP socket */
    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        err_exit("socket SOCK_STREAM error");
    }

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family      = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port        = htons(SERV_PORT);

    if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
        err_exit("setsockopt error");
    }
    if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
        err_exit("bind error");
    }

    if (listen(listenfd, LISTENQ) == -1) {
        err_exit("listen error");
    }

    /* create UDP socket */
    if ((udpfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
        err_exit("socket SOCK_DGRAM error");
    }

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family      = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port        = htons(SERV_PORT);

    if (bind(udpfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
        err_exit("bind error");
    }

    if (my_signal(SIGCHLD, sig_chld) == SIG_ERR) {  /* must call waitpid() */
        err_exit("my_signal error");
    }

    FD_ZERO(&rset);
    maxfdp1 = max(listenfd, udpfd) + 1;
    for ( ; ; ) {
        FD_SET(listenfd, &rset);
        FD_SET(udpfd, &rset);
        if ((nready = select(maxfdp1, &rset, NULL, NULL, NULL)) == -1) {
            if (errno == EINTR) {
                continue;  /* back to for() */
            }
            else {
                err_exit("select error");
            }
        }

        if (FD_ISSET(listenfd, &rset)) {
            len = sizeof(cliaddr);
            connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &len);
            if (connfd == -1) {
                err_exit("accept error");
            }
    
            if ((childpid = fork()) < 0) {
                err_exit("fork error");
            }
            else if (childpid == 0) {
                if (close(listenfd) == -1) {
                    err_exit("close listenfd error");
                }
                str_echo(connfd);  /* process the request */
                exit(0);
            }
            if (close(connfd) == -1) {
                err_exit("close connfd error");
            }
        }

        if (FD_ISSET(udpfd, &rset)) {
            len = sizeof(cliaddr);
            if ((n = recvfrom(udpfd, mesg, MAXLINE, 0, 
                              (struct sockaddr *)&cliaddr, &len)) == -1) {
                err_exit("recvfrom error");
            }

            if (sendto(udpfd, mesg, n, 0, 
                       (struct sockaddr *)&cliaddr, len) == -1) {
                err_exit("sendto error");
            }
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值