C/S架構服務器socket通信的簡單模型搭建

此程序代碼中不包含併發。併發服務器在後續博客陸續推出

程序框圖如下:
在這裏插入圖片描述

server.c

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdlib.h>
#include <string.h>

#define PORT 8888
void sys_err(const char * str)
{
    perror(str);
    exit(-1);
}

int main()
{
	//參數1:IPV4
	//參數2:流式協議
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd == -1)
    {
        perror("socket error");
        exit(-1);
    }

	//端口複用
    int opt = 1;
    int ret = setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
    if(ret == -1)
    {
        sys_err("setsockopt error");
    }

	//bind綁定ip和端口
    struct sockaddr_in ser_addr;
    memset(&ser_addr,0,sizeof(ser_addr));
    ser_addr.sin_family = AF_INET;
    ser_addr.sin_port = htons(PORT);
    ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    ret = bind(sockfd,(struct sockaddr *)&ser_addr,sizeof(ser_addr));
    if(ret == -1)
    {
        sys_err("bind error");
    }

	//設置監聽上限
    ret = listen(sockfd,128);
    if(ret == -1)
    {
        sys_err("listen error");
    }
    printf("accept connecting.....\n");

    struct sockaddr_in cli_addr;
    socklen_t cli_addr_len = sizeof(ser_addr);
    char str[BUFSIZ];
    memset(str,0,sizeof(str));

    char buf[1024];
    memset(buf,0,sizeof(buf));
    int rbytes = 0;
    int wbytes = 0;
    int i = 0;
  
    //阻塞等帶客戶端連接
    int connfd = accept(sockfd,(struct sockaddr *)&cli_addr,&cli_addr_len);
    if(connfd == -1)
    {
         sys_err("accept error");
    }
        
    while(1)
    {
        rbytes = read(connfd,buf,sizeof(buf));
        if(read < 0)
        {
            sys_err("read error");
        }
        else if(rbytes == 0)
        {
            close(connfd);
            return 0;
        }
        else
        {
            for(i = 0;i<rbytes;i++)
            {
                buf[i] = toupper(buf[i]);
            }
        }
        
        write(STDOUT_FILENO,buf,rbytes);

        wbytes = write(connfd,buf,rbytes);

        sleep(1);
    }

    close(sockfd);
    return 0;
}

client.c

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdlib.h>
#include <string.h>

#define PORT 8888
void sys_err(const char * str)
{
    perror(str);
    exit(-1);
}

int main()
{
	//socket建立通信
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd == -1)
    {
        perror("socket error");
        exit(-1);
    }

	//客戶端與服務器建立連接
    struct sockaddr_in ser_addr;
    memset(&ser_addr,0,sizeof(ser_addr));
    ser_addr.sin_family = AF_INET;
    ser_addr.sin_port = htons(PORT);
    inet_pton(AF_INET,"127.0.0.1",&ser_addr.sin_addr);
    int ret = connect(sockfd,(struct sockaddr *)&ser_addr,sizeof(ser_addr));
    if(ret == -1)
    {
        sys_err("connect error");
    }

    char buf[1024];
    memset(buf,0,sizeof(buf));
    int wbytes = 0;
    int rbytes = 0;

    while(1)
    {
        fgets(buf,sizeof(buf),stdin);

        wbytes = write(sockfd,buf,strlen(buf));
        if(wbytes < 0)
        {
            sys_err("read error");
        }
        else if(wbytes == 0)
        {
            close(sockfd);
            return 0;
        }
        
        rbytes = read(sockfd,buf,sizeof(buf));
        if(rbytes < 0)
        {
            sys_err("read error");
        }
        

        wbytes = write(STDOUT_FILENO,buf,rbytes);
        if(wbytes != rbytes)
        {
            sys_err("write error");
        }
    }

    close(sockfd);
    return 0;
}

總結:此篇博客只是簡單熟悉一下socket 通信的API,後續將有併發中select,poll,epoll 以及線程池的併發服務器的博客相繼退出。

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