基本套接字編程

《UNP》第4到第5章講解了基本的TCP套接字編程。先介紹了各類套接字的地址結構,然後詳述了各個API。
先介紹了一個迭代服務器,但是迭代服務器性能有限,所以提供了一個併發服務器。但是併發服務器需要用信號機制處理結束的子進程,並且會帶來中斷慢系統調用的問題。
再升級一下,可以預先派生子進程,可以用線程替代進程,可以把服務器改造爲守護進程等等。

#ifndef UTILS_H
#define UTILS_H

#include <sys/socket.h>
#include <netinet/in.h>
#include <strings.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

//typedef void waitSon(int);
//註冊信號處理程序,需要提供信號和函數指針。
void (*waitSon(int signo, void (*func)(int)))(int);
//建立一個TCP連接,成功返回套接字描述符;失敗返回-1.
int tcp_connect(const char *addr, const char *port);
//成功則返回一個監聽套接字;否則返回-1.
int tcp_listen(const char *port, int backlog);

//建立一個TCP連接,成功返回套接字描述符;失敗返回-1.
int tcp_connect(const char *addr, const char *port)
{
    int                    sockfd;
    struct sockaddr_in     svraddr;

    bzero(&svraddr, sizeof(svraddr));
    svraddr.sin_family      =       AF_INET;
    svraddr.sin_port        =       htons(atoi(port));
    inet_pton(AF_INET, addr, &svraddr.sin_addr);

    if( (sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
    {
        write(2, "socket error\n", 13);
        return -1;
    }

    if(connect(sockfd, (struct sockaddr*) &svraddr, sizeof(svraddr)) == 0)
        return sockfd;
    else
    {
        write(2, "connect error\n", 14);
        return -1;
    }
}

//成功則返回一個監聽套接字;否則返回-1.
int tcp_listen(const char *port, int backlog)
{
    int                     listenfd;
    struct sockaddr_in      svraddr;

    bzero(&svraddr, sizeof(svraddr));
    svraddr.sin_family         =   AF_INET;
    svraddr.sin_port           =   htons(atoi(port));
    svraddr.sin_addr.s_addr    =   htonl(INADDR_ANY);

    if( (listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
    {
        write(2, "socket error\n", 13);
        return -1;
    }

    if( bind(listenfd, (struct sockaddr*)&svraddr, sizeof(svraddr)) < 0)
    {
        write(2, "bind error\n", 11);
        return -1;
    }

    if(listen(listenfd, backlog) < 0)
    {
        write(2, "listen error\n", 13);
        return -1;
    }

    return listenfd;

}

//註冊信號處理程序,需要提供信號和函數指針。
void (*waitSon(int signo, void (*func)(int)))(int)
{
    struct sigaction act,oact;//oact = oldact

    act.sa_handler = func;

    sigemptyset(&act.sa_mask);

    act.sa_flags = 0;
    act.sa_flags |= SA_RESTART;

    if( sigaction(signo, &act, &oact) < 0 )
        return SIG_ERR;
    else
        return oact.sa_handler;
}

#endif
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章