基于TCP的服务器


Liunx

/***************** server.c *******************/
#include <stdlib.h>                                                                                       
#include <stdio.h>                                                                                        
#include <string.h>                                                                                                 
#include <unistd.h>                                                                                       
#include <sys/socket.h>                                                                                   
#include <netinet/in.h>//socket_in                                                                        
#include <arpa/inet.h>                                                                                                  
typedef struct sockaddr sockaddr;                                                                         
typedef struct sockaddr_in sockaddr_in;                                                                   
void ProcessConnect(int new_sock)
{
    while(1)
    {
        char buf[1024] = {0};
        ssize_t read_size = read(new_sock,buf,sizeof(buf)-1);
        if(read_size < 0)
        {
            perror("read");
            continue;
        }
        if(read_size == 0)//读到EOF 客户端断开连接
        {
            printf("[client %d] disconnect!\n",new_sock);
            close(new_sock);
            return;
        }
        buf[read_size] = '\0';
        printf("[client %d] say %s\n",new_sock,buf);

        write(new_sock,buf,strlen(buf));
    }
}






int main(int argc,char* argv[])                                                                           

{
    if(argc != 3)
    {
        printf("Usage ./server [Ip] [port]\n");
        return 1;
    }

    int listen_sock = socket(AF_INET,SOCK_STREAM,0);

    if(listen_sock < 0)
    {
        printf("sock error");
        return 1;
    }
    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(argv[1]);
    addr.sin_port = htons(atoi(argv[2]));

    int ret = bind(listen_sock,(sockaddr*)&addr,sizeof(addr));

    if(ret <0)
    {
        printf("bind error");
        return 1;
    }

    ret = listen (listen_sock,5);//内核最多允许多少客户等待

    if(ret < 0)
    {
        printf("listen error");
        return 1;
    }

    printf("Server start ok\n");

    while(1)
    {
        sockaddr_in peer;
        socklen_t len = 0;
        //socklen_t len = sizeof(peer);
        int new_sock = accept(listen_sock,(sockaddr*)&peer,&len);
        if(new_sock < 0 )
        {
            perror("accept");
            continue;

        }
        printf("[client %d] connect\n",new_sock);
        ProcessConnect (new_sock);

    }
    close(listen_sock);
    return 0;
}

/****************** client.c ********************/
#include <stdio.h>                        
#include <stdlib.h>                         
#include <string.h>                                                   

#include <unistd.h>                         
#include <sys/socket.h>                    
#include <netinet/in.h>//socket_in         
#include <arpa/inet.h>//inet_addr          

typedef struct sockaddr sockaddr;          
typedef struct sockaddr_in sockaddr_in;    

int main(int argc, char* argv[])                       
{                                                      
    if(argc != 3)                                      
    {                                                  
         printf("Usage  ./server [ip]  [port]\n");      
         return 1;                                      
    }            

    int sock = socket(AF_INET,SOCK_STREAM,0);

    if(sock < 0 )
    {
        perror("socket");
        return 1;
    }

    sockaddr_in server_addr;                            
    server_addr.sin_family = AF_INET;                   
    server_addr.sin_addr.s_addr = inet_addr(argv[1]);   
    server_addr.sin_port = htons(atoi(argv[2]));        

    int ret = connect(sock,(sockaddr*)&server_addr, sizeof(server_addr));
    if(ret < 0)
    {
        printf("connect ");
        return 1;
    }

    while(1)                                               
    {                                                      
        printf(">begin>:");                                 
        fflush(stdout);

        char buf[1024] = {0};
        ssize_t read_size = read(0,buf,sizeof(buf)-1);

        if(read_size < 0)
        {
            printf("read");
            return 1;
        }
        if(read_size == 0)
        {
            printf("断开连接");
            return 0;
        }

        buf[read_size] = '\0';

        write(sock,buf,sizeof(buf));

        char buf_output[1024] = {0};
        read_size = read(sock,buf_output,sizeof(buf_output) - 1);
        if(read_size < 0)
        {
            printf("read < 0");
            return 1;
        }
        if(read_size == 0)
        {
            printf("read  = 0");
        }

        buf_output[read_size] = '\0';

        printf("server resp %s\n",buf_output);

    }

    return 0;
}
//为解决上边服务器只能单个客户端访问,以下客户端采用多进程方法改写
//此版本存在效率问题,相对于多线程的版本,后续会有IO多路复用,epool等
//从浅到深  编码风格不同  源于书写时间不同(未改以前)
/****************** server_fork.c *******************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

typedef struct sockaddr sockaddr;
typedef struct sockaddr_in sockaddr_in;


int ServerInit(char* ip,short port){
    int listen_sock = socket(AF_INET,SOCK_STREAM,0);
    if(listen_sock < 0){
        printf("socket");
        return -1;
    }
    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(ip);
    addr.sin_port = htons(port);

    int ret = bind(listen_sock,(sockaddr*)&addr,sizeof(addr));
    if(ret < 0){
        perror("bind");
        return -1;
    }
    ret = listen(listen_sock,5);
    if(ret < 0){
        perror("listen");
        return -1;
    }
    return listen_sock;
}


void ProcessConnect(int new_sock){
    pid_t ret = fork();
    if(ret < 0){
        perror("fork");
        return;
    }
    if(ret == 0){
        while(1){
            char buf[1024] = {0};
            ssize_t read_size = read(new_sock,buf,sizeof(buf)-1);
            if(read_size < 0){
                perror("read");
                exit(1);
            }
            if(read_size == 0){
                printf("[client %d] disconnected! \n",new_sock);
                close(new_sock);
                exit(0);
            }
            buf[read_size] = '\0';
            printf("[client %d] say %s\n",new_sock,buf);

            write(new_sock,buf,strlen(buf));
        }
        exit(0);
    }
    //父进程能够快速再次调用 accept
    close(new_sock);//子进程保存了一份父进程的文件描述表
    //回收子进程  采用忽略信号的方式
}



int main(int argc,char* argv[]){
    if(argc!= 3){
        printf ("Usage ./server [ip] [port]\n");
        return 1;
    }
    //忽略子进程信号 子进程就会被系统自动回收
    signal(SIGCHLD,SIG_IGN);

    int listen_sock = ServerInit(argv[1],atoi(argv[2]));
    if(listen_sock < 0){
        printf ("ServerInit failed!!! \n");
        return 1;
    }

    printf("ServerInit ok!!!  \n");


    while(1){
        sockaddr_in peer;
        socklen_t len = sizeof(peer);
        int new_sock = accept(listen_sock,(sockaddr*)&peer,&len);
        if(new_sock <0){
            perror("accpet");
            continue;
        }
        printf("[client %d] connect!\n",new_sock);
        ProcessConnect(new_sock);
    }

    return 0;
}

/****************** makefile ********************/
.PHONY:all
all:server client server_fork 

server:server.c
    gcc $^ -o $@

client:client.c
    gcc $^ -o $@

server_fork:server_fork.c
    gcc $^ -o $@

.PHONY:clean
clean:
    rm -f server client server_fork 

OSI七层模型:
https://blog.csdn.net/Romantic_C/article/details/81665591
网络套接字:
https://blog.csdn.net/Romantic_C/article/details/81704425
UDP服务器:
https://blog.csdn.net/Romantic_C/article/details/81705468
TCP服务器:
https://blog.csdn.net/Romantic_C/article/details/81707907
应用层:
https://blog.csdn.net/Romantic_C/article/details/81714161
传输层:
https://blog.csdn.net/Romantic_C/article/details/81747317
网络层:
https://blog.csdn.net/Romantic_C/article/details/81751255
数据链路层:
https://blog.csdn.net/Romantic_C/article/details/81777844

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值