Linux网络编程——tcp、udp迭代服务器

一、迭代与并发服务器概述
服务器设计技术有很多,按使用的协议来分有 TCP 服务器和 UDP 服务器,按处理方式来分有迭代服务器(循环服务器)和并发服务器。

在网络程序里面,一般来说都是许多客户对应一个服务器(多对一),为了处理客户的请求,对服务端的程序就提出了特殊的要求。
目前最常用的服务器模型有:
迭代服务器:服务器在同一时刻只能响应一个客户端的请求

并发服务器:服务器在同一时刻可以响应多个客户端的请求

二、UDP 迭代服务器
UDP 循环服务器每次从套接字上读取一个客户端的请求 -> 处理 -> 然后将结果返回给客户机。
因为 UDP 是非面向连接的,没有一个客户端可以老是占住服务端。只要处理过程不是死循环,或者耗时不是很长,服务器对于每一个客户机的请求在某种程度上来说是能够满足。
udp迭代服务器框架:

//1.创建套接字  
int sockfd = socket(...);  
  
//2.绑定套接字  
bind(...);  
  
while(1)  
{  
    //3.接收客户端的请求  
    recvfrom(...);  
      
    //4.处理客户端的请求  
    process(...);  
      
    //5.反馈处理结果  
    sendto(...);  
}  

udp迭代服务器参考代码:

#include   
#include   
#include   
#include   
#include   
#include   
#include   
  
int main(int argc, char *argv[])  
{  
    unsigned short port = 8080; //本地端口  
  
    //1.创建udp套接字  
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);   
    if(sockfd < 0)  
    {  
        perror("socket");  
        exit(-1);  
    }  
      
    // 配置本地网络信息  
    struct sockaddr_in my_addr;  
    bzero(&my_addr, sizeof(my_addr));   // 清空  
    my_addr.sin_family = AF_INET;       // IPv4  
    my_addr.sin_port   = htons(port);   // 端口  
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // ip  
      
    printf("Binding server to port %d\n", port);  
      
    // 2.绑定套接字  
    int err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));  
    if(err_log != 0)  
    {  
        perror("bind");  
        close(sockfd);        
        exit(-1);  
    }  
      
    printf("receive data...\n");  
    while(1)  
    {  
        int recv_len;  
        char recv_buf[512] = {0};  
        struct sockaddr_in client_addr;  
        char cli_ip[INET_ADDRSTRLEN] = "";//INET_ADDRSTRLEN=16  
        socklen_t cliaddr_len = sizeof(client_addr);  
          
        //3.接收客户端的请求  
        recv_len = recvfrom(sockfd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr*)&client_addr, &cliaddr_len);  
          
        //4.处理客户端的请求,这里只是把接收过来的数据打印  
        inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN);  
        printf("\nip:%s ,port:%d\n",cli_ip, ntohs(client_addr.sin_port)); // 客户端的ip  
        printf("data(%d):%s\n",recv_len,recv_buf);  // 客户端的数据  
          
        //5.反馈处理结果,这里把接收直接到客户端的数据回复过去  
        sendto(sockfd, recv_buf, recv_len, 0, (struct sockaddr*)&client_addr, cliaddr_len);  
    }  
      
    close(sockfd);  
      
    return 0;  
}  

运行结果:


Linux网络编程——tcp、udp迭代服务器_第1张图片

三、tcp迭代服务器
TCP 迭代服务器接受一个客户端的连接,然后处理,完成了这个客户的所有请求后,断开连接。TCP 迭代服务器一次只能处理一个客户端的请求,只有在这个客户的所有请求满足后,服务器才可以继续后面的请求。如果有一个客户端占住服务器不放时,其它的客户机都不能工作了,因此,TCP 服务器一般很少用迭代服务器模型的。

tcp迭代服务器框架:

//1.创建tcp套接字  
int sockfd = socket(...);  
  
//2.绑定套接字  
bind(...);  
  
//3.监听套接字  
listen(...);  
  
while(1)  
{  
    //4.提取已连接套接字  
    int connfd = accept(...);  
      
    //5.处理客户端的请求  
    process(...);  
      
    //6.关闭已连接套接字  
    close(connfd);  
}  
  
//7.关闭监听套接字  
close(sockfd);  

tcp迭代服务器参考代码:

#include   
#include   
#include                          
#include   
#include   
#include   
#include   
              
int main(int argc, char *argv[])  
{  
    unsigned short port = 8080;     // 本地端口   
  
    //1.创建tcp套接字  
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);     
    if(sockfd < 0)  
    {  
        perror("socket");  
        exit(-1);  
    }  
      
    //配置本地网络信息  
    struct sockaddr_in my_addr;  
    bzero(&my_addr, sizeof(my_addr));     // 清空     
    my_addr.sin_family = AF_INET;         // IPv4  
    my_addr.sin_port   = htons(port);     // 端口  
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // ip  
      
    //2.绑定  
    int err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));  
    if( err_log != 0)  
    {  
        perror("binding");  
        close(sockfd);        
        exit(-1);  
    }  
      
    //3.监听,套接字变被动  
    err_log = listen(sockfd, 10);   
    if(err_log != 0)  
    {  
        perror("listen");  
        close(sockfd);        
        exit(-1);  
    }     
      
    printf("listen client @port=%d...\n",port);  
  
    while(1)  
    {     
      
        struct sockaddr_in client_addr;          
        char cli_ip[INET_ADDRSTRLEN] = "";       
        socklen_t cliaddr_len = sizeof(client_addr);      
          
        //4.取出客户端已完成的连接  
        int connfd;  
        connfd = accept(sockfd, (struct sockaddr*)&client_addr, &cliaddr_len);         
        if(connfd < 0)  
        {  
            perror("accept");  
            continue;  
        }  
  
        //5.打印客户端的ip和端口  
        inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN);  
        printf("----------------------------------------------\n");  
        printf("client ip=%s,port=%d\n", cli_ip,ntohs(client_addr.sin_port));  
          
        // 接收数据  
        char recv_buf[512] = {0};  
        int len =  recv(connfd, recv_buf, sizeof(recv_buf), 0);  
          
        // 处理数据,这里只是打印接收到的内容  
        printf("\nrecv data:\n");  
        printf("%s\n",recv_buf);  
          
        // 反馈结果  
        send(connfd, recv_buf, len, 0);  
          
        //6.关闭已连接套接字  
        close(connfd);       
        printf("client closed!\n");  
    }  
      
    //7.关闭监听套接字  
    close(sockfd);           
      
    return 0;  
}  

运行结果:


Linux网络编程——tcp、udp迭代服务器_第2张图片

你可能感兴趣的:(Linux网络编程——tcp、udp迭代服务器)