美文网首页
服务器的实现

服务器的实现

作者: 天明code | 来源:发表于2020-05-21 10:33 被阅读0次
#include "include/net.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
int main()
{
    /**
     * 为了执行网络I/O,一个进程必须做的第一件事情就是创建一个socket函数
     * int socket(int family, int type, int protocol);
     * family 表示协议族     AF_INET(IPv4协议)、AF_INET6(IPv6协议)、AF_LOCAL(Unix域协议)、
     *         AF_ROUTE(路由套接字)、AF_KEY(  密钥套接字)
     * type 表示套接字类型   SOCK_STREAM(字节流套接字)、SOCK_DGRAM(数据报套接字)、
     *      SOCK_SEQPACKET(有序分组套接字)、SOCK_ROW(原始套接字)
     *  protocol 表示传输协议 IPPROTO_TCP(TCP传输协议)、IPPROTO_UDP(UDP传输协议)、
     *      IPPROTO_SCTP(SCTP传输协议)
     *   若成功返回非负描述符,若出错返回-1
     */
      printf("1,\n");
    int listenfd = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP); //IPv4, 字节流套接字, tcp协议

    if(listenfd < 0){
        printf("socket error \n");
        return -1;
    }

     printf("socket success \n");
 
    /**
     * struct sockaddr_in {
     *  uint8_t sin_len;    //结构体长度
     *  sa_family_t sin_family; //AF_INET
     *  in_port_t sin_port; //端口(16-bie)
     *  struct in_addr sin_addr; //IPv4地址(32-bit)
     *  char sin_zero[8]; //冗余,设置0即可
     */
    struct sockaddr_in svraddr;/*声明一个变量,类型为协议地址类型*/
    svraddr.sin_family = AF_INET;/*使用IPv4协议*/
    svraddr.sin_port = htons(80);/*监听8887端口*/
    svraddr.sin_addr.s_addr = htonl(INADDR_ANY);/*绑定本机IP,使用宏定义绑定*/

        int open = 1;
    //   // 开启reuse
    // if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &open, sizeof(open)) == -1) {
    //     return -1;
    // }

    // // 关闭nagle
    // if (setsockopt(listenfd, IPPROTO_TCP, TCP_NODELAY, &open, sizeof(open)) == -1) {
    //     return -1;
    // }
    
    /**
     * bind函数把一个本地协议地址赋予一个套接字,对于网际协议,协议地址就是IP加端口的组合
     * int bind(int sockfd, const struct sockaddr * myaddr, socklen_t addrlen)
     * sockfd  初始化的套接字
     *  myaddr 协议地址
     *  addrlen  协议地址长度
     *  若成功返回0 出错返回-1
     */
    if(bind(listenfd ,(struct sockaddr*)&svraddr,sizeof(svraddr)) < 0){
        printf("bind error \n");
        return -1;
    }

    printf("bind success \n");


    /**
     * int listen(int sockfd, int backlog)
     * sockfd当使用socket函数创建一个套接字时,它被假设为一个主动套接字,也就是说,它是一个将发送connect发起连接的客户端套接字。
     *  当调用listen函数之后,它被转成一个被动套接字,只是内核应该接受连接请求。所以,调用listen之后套接字由CLOSED状态转到LISTEN状态;
     *backlog  这个函数规定内核应该为相应套接字排队的最大连接数
     * (1)未完成连接队列,在客户端发送一个SYN直到三次握手完成,都是这个状态,SYN_RCVD状态
     * (2)已完成连接队列,这个表示三次握手完成的状态,ESTABLISHED状态
     * 失败时返回-1
     */

    if(listen(listenfd, 20) < 0){
        printf("listen error \n");
        return -1;
    }

    /**
     * int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
     * sockdf 服务器套接字莫描述符
     * cliaddr 已连接的客户端协议地址
     * addrlen 已连接的客户端协议地址长度
     *  成功返回非负描述符,出错返回-1
     */
    struct sockaddr_in cliaddr; /*只是声明,并没有赋值*/
    memset(&cliaddr, 0, sizeof(cliaddr));
    socklen_t ret = sizeof(cliaddr);
    int sockfd= accept(listenfd, (struct sockaddr*)&cliaddr, &ret );

    if(sockfd < 0){
        printf("appect error \n");
        return -1;
    }

    printf("appect success \n");


    /**
     * 这些函数直接在存储器和文件之间传送数据,没有应用级缓冲。对将二进制数据读写到网络和从网络读写二进制数据尤其有用
     * ssize_t rio_readn(int fd, void *usrbuf, size_t n) 
     * ssize_t read(int fd,void*buf,size_t count) 
     *  fd: 是文件描述符, 从command line获取数据时,为0
     *  buf: 为读出数据的缓冲区;
     * count: 为每次读取的字节数(是请求读取的字节数,读上来的数据保存在缓冲区buf中,同时文件的当前读写位置向后移)
     */

    //处理接收到的字符;
    // char *p;

    // p = (char*)malloc(MAXLEN*(sizeof(char*)));   //申请一块内存,存放读取数据
    // memset(p,0,1);
    // ret = read(0,p,MAXLEN);

    char str[] = "HTTP/1.1 200 OK\r\nContent-Length:11\r\n\r\n hello world";

    /** sockfd socket文件描述符
    *   buf 文件内容
    *   count 内容长度
    *  ssize_t write(int sockfd, const void * buff, size_t count);
     **/
    write(sockfd , str, sizeof(str));



    close(sockfd );
    close(listenfd);
}


相关文章

网友评论

      本文标题:服务器的实现

      本文链接:https://www.haomeiwen.com/subject/euxzohtx.html