计算机网络编程基础

判断主机字节序的程序:

int main(int argc, char **argv){
    union{
        short s;
        char c[sizeof(short)];
    }un;
    un.s = 0×0102;
    if(sizeof(short) == 2){
        if(un.c[0]==1 && un.c[1]==2)
            printf("BigEndian");
        else if(un.c[0]==2 && un.c[1]==1)
            printf("LittleEndian");
        else
            printf("unknown");
    }else{
        printf("sizeof(short): %d", sizof(short));
        exit(0);
    }

}

字节序转换的函数 ntohs/htons: 网络到主机用ntohs,主机到网络htons。

ILP\LP\LLP:

Linux用LP64

Windows LLP64

对齐系数:每个特定平台的编译器都有自己的对齐系数。可以通过预编译命令#progma pack(n),n=1,2,4,8,16来改变这一系数。

 packed格式压缩结构体:

struct{
    u16 id;
    u64 lun;
    u16 reserved1;
    u32 reserved2;
}__attribute__((packed))
  • IPV4的一些结构体
  • struct sockaddr_in{
        unit8_t sin_len;
        sa_family_t sin_family;
        in_port_t sin_port;
        struct in_addr sin_addr;
        char sin_zero[8]; 
        
    }
    
    struct in_addr{
        in_addr_t s_addr;
    }

    地址转换函数:

  • int inet_aton(char*, struct in_addr *);//将ascii码的IP地址转换为network网络字节序32位的IPV4bit值,1成功0失败
    char *inet_ntoa(struct in_addr);//将network网络字节序转换为ascii码的点分十进制的字符串(xx.xx.xx.xx)
    int inet_pton(int 地址族(4或6), const char * ,void *);//将protocol协议字符串转换为IPV4/6bit值
    int *inet_ntop(int 地址族(4或6), const void* 地址结构体, char* 字符串, size_t length);//将network网络字节序转换为点分十进制的字符串
    

     

  • 常用API
  • inet_addr
  • gethostbyname
  • getservbyname
  • getprotobynumber

 

Epoll

#include <sys/socket.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>

#define MAXLINE 4096
#define LISTENQ 20
#define SERV_PORT 6666

int main(int argc, char *argv[])
{
    int i, maxi, listenfd, connfd, sockfd, epfd, nfds;
    ssize_t n;
    char BUF[MAXLINE];
    socklen_t clilen;

    clilen=sizeof(struct sockaddr);
    //ev用于注册事件,数组用于回传要处理的事件

    struct epoll_event ev, events[20];
    //生成用于处理accept的epoll专用的文件描述符

    epfd = epoll_create(256);
    struct sockaddr_in cliaddr, servaddr;
    listenfd = socket(AF_INET, SOCK_STREAM, 0);

    //setnonblocking(listenfd);
    //设置与要处理的事件相关的文件描述符

    ev.data.fd = listenfd;
    ev.events = EPOLLIN | EPOLLET;
    //注册epoll事件

    epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev);

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(6666);
    bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    listen(listenfd, LISTENQ);
    maxi = 0; //useless
    for (;;)
    {
        nfds = epoll_wait(epfd, events, 20, 0);

        for (i = 0; i < nfds; ++i)
        {
            if (events[i].data.fd == listenfd) //如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口,建立新的连接。
            {
                connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
                // printf("\n当前连接的客户端 ip: %s port: %d", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));

                if (connfd < 0)
                {
                    perror("connfd<0");
                    exit(1);
                }
                //setnonblocking(connfd);

                char *str = inet_ntoa(cliaddr.sin_addr);
                // printf("accept a connection from %s\n", str);

                ev.data.fd = connfd;
                ev.events = EPOLLIN | EPOLLET;
                printf("当前连接的客户端 ip: %s port: %d\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));

                epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &ev);
            }
            else if (events[i].events & EPOLLIN)
            //如果是已经连接的用户,并且收到数据,那么进行读入。

            {
                if ((sockfd = events[i].data.fd) < 0)
                    continue;
                if ((n = read(sockfd, BUF, MAXLINE)) < 0)
                {
                    if (errno == ECONNRESET)
                    {
                        close(sockfd);
                        events[i].data.fd = -1;
                    }
                    else
                        printf("readline error\n");
                }
                else if (n == 0)
                {
                    close(sockfd);
                    events[i].data.fd = -1;
                }
                BUF[n] = '\0';
                write(sockfd, BUF, n);

                ev.data.fd = sockfd;
                ev.events = EPOLLOUT | EPOLLET;
                //读完后准备写
                epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
            }
            else if (events[i].events & EPOLLOUT) // 如果有数据发送

            {
                sockfd = events[i].data.fd;
                write(sockfd, BUF, n);

                ev.data.fd = sockfd;
                ev.events = EPOLLIN | EPOLLET;
                //写完后,这个sockfd准备读
                epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev);
            }
        }
    }
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值