基于TCP协议的服务器编程

#include<netdb.h>
#include<sys/socket.h>
#include<unistd.h>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
#include<signal.h>
#include<time.h>

int sockfd;

void sig_handler(int signo)
{
    if(signo == SIGINT)
    {
        printf("server close ");
    /*
    *    步骤6:关闭socket
    */
        close(sockfd);
        exit(1);
    }
}

/*输出连接上来的客户端相关信息*/
void  out_addr(struct sockaddr_in *clientaddr)
{
    //将端口从网络字节序转换成主机字节序
    int port = ntohs(clientaddr->sin_port);
    char ip[16];
    memset(ip ,0,sizeof(ip));
    //将ip地址从网络字节序转换成点分十进制
    inet_ntop(AF_INET,&clientaddr->sin_addr.s_addr,ip,sizeof(ip));
    printf("client:%s(%d) connected ",ip,port);
}

void do_service(int fd)
{
    //获得系统时间
    long t = time(0);
    char *s =ctime(&t);//转成字符串形式
    size_t size = strlen(s) * sizeof(char);
    //将服务器端获得的系统时间写回到客户端
    if(write(fd,s,size) != size )
    {
        perror("write error");
    }
}



int main(int argc,char *argv[])
{
    if(argc < 2)
    {
        printf("usage: %s #port ", argv[0]);
        exit(1);
    }
    if(signal(SIGINT,sig_handler) == SIG_ERR)
    {
        perror("signal sigint error");
        exit(1);
    }
    
    /*步骤1:创建socket(套接字)
     *       注:socket创建在内核中,是一个结构体
     *       AF_INET:IPV4
     *       SOCK_STREAM:tcp协议
    */
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    if (sockfd < 0)
    {
        perror("socket error");
        exit(1);
    }
    
    /*
    * 步骤2:调用bind函数将socket和地址(包括ip、port)进行绑定
    */
    struct sockaddr_in serveraddr;
    memset(&serveraddr,0,sizeof(serveraddr));
    //往地址中填入ip、port、internet地址族类型
    serveraddr.sin_family = AF_INET;//IPV4    
    serveraddr.sin_port = htons(atoi(argv[1]));//端口
    serveraddr.sin_addr.s_addr = INADDR_ANY;
    if(bind(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr) < 0 )
    {
        perror("bind error");
        exit(1);
    }
    
    /*
    * 步骤3: 调用listen函数启动监听(指定port监听)
    *         通知系统去接受来自客户端的连接请求
    *         将接受到的客户端连接请求放置到对应的队列中
    *         第二个参数:指定队列的长度
    */
    if(listen(socket,10) < 0 )
    {
        perror("listen error");
        exit(1);
    }
    
    /*
    *  步骤4: 调用accept函数从队列当中获得一个客户端的请求连接
    *           并返回新的socket描述符
    *  注意:  若没有客户端连接,调用此函数后会阻塞,
    */
    struct sockaddr_in clientaddr;
    socklen_t clientaddr_len = sizeof(clientaddr);
    while(1)
    {
        int fd = accept(sockfd,(struct sockaddr*)&clientaddr,&clientaddr_len);
        if(fd < 0)
        {
            perror("accept error");
            continue;
        }
    /*
    *   步骤5: 调用I/O函数(read/write)和连接的客户端进行双向的通信
    */    
    out_addr(&clientaddr);
    do_service(fd);
    /*
    *    步骤6:关闭socket
    */
    close(fd);
    
    }
  
    return 0;
}


原文地址:https://www.cnblogs.com/lvdh1314/p/6478048.html