UNP《网络编程》笔记 第一章 简介

第一章主要通过一个获取时间的客户端程序client和时间获取服务器程序server来简单介绍网络通信的一些基本套接字
API。通过这些API函数对网络通信有一个大致的了解。在官网上下载源码点我点我,按照README里面的步骤进行编译,当在libfree编译时候可能会有这样的错误


修改inet_ntop.c的第60行,将size_t size ->改成 socklen_t size 。

然后再按照README里面的流程进行编译即可

客户端程序(代码路径./intro/daytimetcpcli.c 下载地址上面已给出)

#include        "unp.h"

int
main(int argc, char **argv)
{
        int                                     sockfd, n;
        char                            recvline[MAXLINE + 1];
        struct sockaddr_in      servaddr;

        if (argc != 2)
                err_quit("usage: a.out <IPaddress>");

        if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
                err_sys("socket error");

        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port   = htons(13);        /* daytime server */
        if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
                err_quit("inet_pton error for %s", argv[1]);

        if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)
                err_sys("connect error");

        while ( (n = read(sockfd, recvline, MAXLINE)) > 0) {
                recvline[n] = 0;        /* null terminate */
                if (fputs(recvline, stdout) == EOF)
                        err_sys("fputs error");
        }
        if (n < 0)
                err_sys("read error");

        exit(0);
}

常用函数

1. int socket(intdomain, inttype, intprotocol)

domain:  协议族 AF_INET、AF_INET6、AF_LOCAL。

type:   socket类型,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET     等。SOCK_STREAM是流式套接字,是面向连接的套接字,SOCK_DGRAM是数据报套接字。

protocol常用的协议有,IPPROTO_TCPIPPTOTO_UDPIPPROTO_SCTPIPPROTO_TIPC等,它们分别       对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。

 返回值:是一个小整数描述符,以后的很多函数调用都会用到这个套接字,例如connect、read等


    struct sockaddr_in 定义的位置在 /usr/include/netinet/in.h 中,

/* Structure describing an Internet socket address.  */
struct sockaddr_in
  {
    __SOCKADDR_COMMON (sin_);		/*协议族*/
    in_port_t sin_port;                 /* Port number.  端口号*/
    struct in_addr sin_addr;            /* Internet address. IP地址 */

    /* Pad to size of `struct sockaddr'.  */
    unsigned char sin_zero[sizeof (struct sockaddr) -
                           __SOCKADDR_COMMON_SIZE -
                           sizeof (in_port_t) -
                           sizeof (struct in_addr)];
  };

我们需要解释一下sin_zero,他的作用是填充sockaddr_in 结构体,使他能与sockaddr长度相等,使用中 sockadd_in就可以与sockadd进行转化了。

htons(),htonl(),ntohs(),ntohl()函数是我们经常使用的转换函数,实现网络字节序和主机字节序之间的转换。

inet_pton()可以在将IP地址在“点分十进制”和“二进制整数”之间转换.将我们输入的点分十进制转换为合适的格式。


int connect(intsockfd, struct sockaddr *serv_addr, intaddrlen);

函数作用:用来将参数sockfd 的socket 连至参数serv_addr 指定的网络地址。


时间获取服务器程序(代码路径./intro/ daytimetcpsrv.c 下载地址上面已给出)

#include        "unp.h"
#include        <time.h>

int
main(int argc, char **argv)
{
        int                                     listenfd, connfd;
        struct sockaddr_in      servaddr;
        char                            buff[MAXLINE];
        time_t                          ticks;

        listenfd = Socket(AF_INET, SOCK_STREAM, 0);

        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family      = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port        = htons(13);   /* daytime server */

        Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));

        Listen(listenfd, LISTENQ);

        for ( ; ; ) {
                connfd = Accept(listenfd, (SA *) NULL, NULL);

        ticks = time(NULL);
        snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
        Write(connfd, buff, strlen(buff));

                Close(connfd);
        }
}

主要函数:

int bind(int sockfdconst struct sockaddr *addr,socklen_t *addrlen);

函数作用:当我们调用socket()创建一个套接字完成时候,并没有地址与其关联,调用bind函数以后,该socketfd

就与addr相关联,任何与addr的通信,我们都可以通过sockfd进行read数据和write数据。bind函数并不是必须的,一

般在客户端并不会bind()具体的ip和port,只有在服务器端,我们才需要为服务器端提供固定IP和port,方便客户端进行

访问。

参数sockfd :调用socket后返回的套接字。

参数addr :需要绑定的地址。

int listen(intsockfd, intbacklog);

函数作用:将一个主动套接字转换为一个被动套接字。使该套接字可以接受链接,编程一个服务器。

参数sockfd当我们调用socket()返回一个套接字,系统默认它是一个主动套接字,系统会认为他会去调用connect

函数去链接其他的套接字,这是就需要我们调用listen函数,来告知系统我是被动等待别人来链接的。

参数backlog:TCP链接需要进行三次握手,是一个过程需要一定的时间,当大量的连接请求过来时,系统无法

及时完成连接,这时候就存在一些半连接状态,而这种状态我们不可能让他无限多,需要设置一个最大值。内核会在自

己的进程空间里维护一个队列以跟踪这些完成的连接但服务器进程还没有接手处理或正在进行的连接。


int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);

函数作用:从监听队列中提取出第一个链接请求,并创建一个新的套件字,并且返回这个套接字的描述符,用于接

下来read()和write()。

参数sockedsockfd是一个调用listen()后一直处于监听的队列,

参数addr:用于存储收到的连接的地址。

参数addrlenaddr的长度。



OSI模型一共分为七层,我们这里需要重点了解的是从顶上三层到传输层的接口。上面三层处理的具体的网络应用,很少涉及通信的细节,下面四层不会处理通信的细节,但是处理所有的通信细节。上面三层构成了用户进程,下面四层是内核的一部分,所以四层和五层之间是构建API的自然位置。

参考文献:
http://blog.csdn.net/david_xtd/article/details/7090590

http://c.biancheng.net/cpp/html/354.html

http://blog.csdn.net/zhangzheng0413/article/details/8188967

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值