UNIX网络编程笔记 第三章 套接字编程简介

套接字编程简介

  • IPV4套接字地址结构sockaddr_in
#include <netinet/in.h>

struct in_addr {
    in_addr_t s_addr; //32bit
}

struct sockaddr_in {
    uint8_t        sin_len;        //
    sa_family_t    sin_family;     //AF_INET
    in_port_t      sin_port;       //16bit
    struct in_addr sin_addr;
    char           sin_zero[8];
}
  • IPv6套接字地址结构
#include <netinet/in.h>

struct in6_addr {
    unit8_t s6_addr[16];
}

struct sockaddr_in6 {
    uint8_t          sin6_len;
    sa_family_t      sin6_family;
    in_port_t        sin6_port;
    uint32_t         sin6_flowinfo;
    struct in6_addr  sin6_addr;
    uint32_t         sin6_scope_id;
}
  • 通用套接字地址结构
#include <sys/socket.h>

struct sockaddr {
    uint8_t      sa_len;
    sa_family_t  sa_family;
    char         sa_data[14]; //protocol-specific address
}
//很多方法中都是使用sockaddr
bind(socked,(struct sockaddr*) &serv,sizeof(serv));
  • 新的通用套接字地址结构
#include <netinet/in.h>

struck sockaddr_storage {
    uint8_t ss_len;
    sa_family_t  ss_family;
    /*
    用户透明内容
    */
}
/*
sockaddr_storage能够满足最苛刻的对齐要求。
sockaddr_storage足够大,能够满足系统支持的任何套接字地址结构。
sockaddr_storage中除了ss_len和ss_family之外,其他字段对用户来说是透明的。sockaddr_storage结构必须强制转换成或复制到适合于ss_family的套接字地址结构中,才能访问其他字段。
*/
  • 头文件
int8_t          <sys/types.h>
uint8_t         <sys/types.h>
int16_t         <sys/types.h>
uint16_t        <sys/types.h>
int32_t         <sys/types.h>
uint32_t        <sys/types.h>
sa_family_t     <sys/socket.h>
socklen_t       <sys/socket.h>
in_addr_t       <netinet/in.h>
in_port_t       <netinet/in.h>
  • 值-结果参数
 //参数为指针,可以两个方向互相传值,相应函数有:
 getpeername(int socked, struct sockaddr *addr, int * len)
 select函数中间的3个参数
 getsockopt函数的长度参数
 msghdr结构中的msg_namelen和msg_controllen字段(recvmsg函数使用)
 ifconf结构中的ifc_len字段
 sysctl函数两个长的参数中的第一个
  • 字节序
    字节值的低序位存储在内存起始地址叫小端字节序。
    字节值的高序位存储在内存起始地址叫大端字节序。
    网络协议使用大端字节序。
#include <netinet/in.h>

uint16_t htons(uint16_t host16bitvalue);
uint32_t htonl(uint32_t host32bitvalue);

uint16_t ntohs(uint16_t net16bitvalue);
uint32_t ntohl(uint32_t net32bitvalue);

//h==host n==network l==long s==short
  • 函数
//**************************************************
#include <strings.h>
void bzero(void *dest, size_t nbytes);
void bcopy(void *src, void *dest, size_t nbytes);
int bcmp(const void *ptr1, const void *ptr2, size_t nbytes);//相等返回0,否则返回非0

//**************************************************
#include <arpa/inet.h>
int inet_aton(const char *strptr, struct in_addr *addrptr);
in_addr_t inet_addr(const char *strptr);
char *inet_ntoa(struct in_addr inaddr);
//上面三个只适用于IPv4,下面两个同时适用于IPv4和IPv6
int inet_pton(int family, const char *strptr, void *addr);//成功返回1,若输入不是有效的表达式格式返回0,若出错返回-1
int inet_ntop(int family ,const void *addr, char *strprt, size_t len);//若成功返回指向结果的指针,若出错返回NULL

//**************************************************
#include <unistd.h>
ssize_t read(int fd,void *buf,size_t nbytes);//返回读出的字节数,0表示连接已经关闭?,负数表示出错(一般需要判断errno是否是中断EINTR)
ssize_t write(int fd,const void *buf,size_t nbytes)//返回写入的字节数,负数表示出错(一般需要判断errno是否是中断EINTR)
  • 请求时间程序,服务端代码
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <time.h>

typedef struct sockaddr SA;
typedef struct sockaddr_in SAIN;

int main(int argc, char **argv) {

    int listenfd,clientfd;
    SAIN serverAddr,clientAddr;
    char buf[400];

    bzero(&serverAddr,sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serverAddr.sin_port = htons(45000);

    if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        printf("socket error");
        return 1;
    }


    if( 0 != bind(listenfd,(SA*)&serverAddr,sizeof(serverAddr))){
        printf("bind error");
        close(listenfd);
        return 1;
    }


    if( 0 != listen(listenfd,10)){
        printf("listen error");
        close(listenfd);
        return 1;
    }


    socklen_t addrLen = sizeof(clientAddr); 
    while(1) {
        if((clientfd = accept(listenfd,(SA*)&clientAddr,&addrLen)) > 0) {           

            inet_ntop(AF_INET,&clientAddr.sin_addr.s_addr,buf,sizeof(buf));
            printf("connect from %s:%d\r\n",buf,clientAddr.sin_port);

            int readLen = read(clientfd,buf,sizeof(buf));
            if(readLen < 0)
                printf("read error");
            else{
                buf[readLen] = 0;
                printf("MSG from client:%s\r\n",buf);
            }

            time_t ticks = time(NULL);
            snprintf(buf,sizeof(buf),"%.24s\r\n",ctime(&ticks));
            if(write(clientfd,buf,sizeof(buf)) < 0) {
                if(errno == EINTR)
                    printf("EINTR");
                else {
                    printf("write error");
                    close(clientfd);
                }
            }

        }
    }

    close(listenfd);

    return 0;
}
  • 请求时间程序,客户端代码
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>


typedef struct sockaddr SA;
typedef struct sockaddr_in SAIN;


int main(int argc, char **argv) {


    int sockfd;
    SAIN serverAddr;

    bzero(&serverAddr, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    inet_pton(AF_INET,"127.0.0.1",&serverAddr.sin_addr.s_addr);
    serverAddr.sin_port = htons(45000);

    if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) {
        printf("socket error");
        return 1;
    }   


    if ( 0 != connect(sockfd, (SA *)&serverAddr, sizeof(serverAddr))){
        printf("connect error");
        close(sockfd);
        return 1;
    }

    int writeLen,readLen;

    if ((writeLen = write(sockfd,"hello,what is the time?",23)) < 0) {
        printf("write error");
        close(sockfd);
        return 1;
    }
    char buf[400];
    if( (readLen = read(sockfd,buf,sizeof(buf))) < 0 ) {
        if(errno == EINTR)
            printf("EINTR");
        else {
            printf("read error");
            close(sockfd);
            return 1;
        }
    }else if(readLen == 0) {
        printf("readlen = 0");
        close(sockfd);
        return 1;   
    }else{
        printf("%s",buf);
    }


    close(sockfd);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值