壹 、互连网协议

国标化组织(ISO)定义了互连网协议的主干框架,被称为OSI模型。OSI模型包蕴应用层、表示层、会话层、传输层、互联网层、数据链路层及物理层。而OSI模型过于复杂于今尚未赢得实际的选择。

TCP/IP协议模型将OSI的7层协议模型简化为4层,从而更便于贯彻和采纳。TCP/IP协议模型包含应用层、传输层、互联网层、互连网接口层。

TCP/IP协议与OSI模型的相应关系如下图:

澳门金沙国际 1

 

1.1 互联网常识

#include <sys/types.h>          

Linux Socket编程

我们熟知音讯交换的市场股票总值,那网络中经过之间怎么通讯,如我们每天打开浏览器浏览网页时,浏览器的进度怎么与web服务器通讯的?当你用QQ聊天时,QQ进度怎么与服务器或你好友所在的QQ进度通讯?那几个都得靠socket?那怎么是socket?socket的档次有怎么样?还有socket的大旨函数,那一个都以本文想介绍的。本文的要害内容如下:

1、网络中进程之间如何通信?
2、Socket是什么?
3、socket的基本操作
    3.1、socket()函数
    3.2、bind()函数
    3.3、listen()、connect()函数
    3.4、accept()函数
    3.5、read()、write()函数等
    3.6、close()函数
4、socket中TCP的三次握手建立连接详解
5、socket中TCP的四次握手释放连接详解
6、一个例子(实践一下)
7、留下一个问题,欢迎大家回帖回答!!!

一 、网络中经过之间怎么着通讯?

地点的历程间通讯(IPC)有很多样格局,但可以计算为下边4类:

消息传递(管道、FIFO、消息队列)
同步(互斥量、条件变量、读写锁、文件和写记录锁、信号量)
共享内存(匿名的和具名的)
远程过程调用(Solaris门和Sun RPC)

但这么些都不是本文的大旨!我们要商讨的是网络中经过之间怎么通讯?首要化解的标题是怎么唯一标识2个进程,不然通讯无从谈起!在地点能够经过进度PID来唯一标识二个经过,不过在网络中那是不行的。其实TCP/IP协议族已经帮大家缓解了那几个难点,网络层的“ip地址”能够唯一标识网络中的主机,而传输层的“协议+端口”能够唯一标识主机中的应用程序(进度)。那样利用长富组(ip地址,协议,端口)就足以标识网络的进度了,网络中的进程通讯就可以使用那几个标志与其余进程展开交互。

使用TCP/IP协议的应用程序平常选用选取编制程序接口:UNIX
BSD的套接字(socket)和UNIX System
V的TLI(已经被淘汰),来贯彻网络进度之间的通讯。就现阶段而言,大致全体的应用程序都以利用socket,而现行反革命又是网络时期,互连网中经过通讯是无处不在,那正是自小编为何说“一切皆socket”。
2、什么是Socket?

地方大家曾经清楚网络中的进度是经过socket来通讯的,这如何是socket呢?socket起源于Unix,而Unix/Linux基本管理学之一便是“一切皆文件”,都能够用“打开open
–> 读写write/read –>
关闭close”形式来操作。小编的驾驭就是Socket就是该方式的三个贯彻,socket便是一种独特的公文,一些socket函数正是对其展开的操作(读/写IO、打开、关闭),这一个函数大家在前边举办介绍。

socket一词的起源

在组网领域的首次使用是在1970年2月12日发布的文献IETF RFC33中发现的,撰写者为Stephen Carr、Steve Crocker和Vint Cerf。根据美国计算机历史博物馆的记载,Croker写道:“命名空间的元素都可称为套接字接口。一个套接字接口构成一个连接的一端,而一个连接可完全由一对套接字接口规定。”计算机历史博物馆补充道:“这比BSD的套接字接口定义早了大约12年。”

叁 、socket的基本操作

既然socket是“open—write/read—close”方式的一种完成,那么socket就提供了那些操作对应的函数接口。上边以TCP为例,介绍几个宗旨的socket接口函数。
3.1、socket()函数

int socket(int domain, int type, int protocol);

socket函数对应于普通文书的打开操作。普通文书的打开操作再次回到三个文件讲述字,而socket()用于创制2个socket描述符(socket
descriptor),它唯一标识一个socket。那几个socket描述字跟文件讲述字一样,后续的操作都有使用它,把它当做参数,通过它来进展局地读写操作。
正如能够给fopen的流传不一样参数值,以开辟不一样的公文。创立socket的时候,也得以钦定不相同的参数创设差别的socket描述符,socket函数的八个参数分别为:

domain:即协议域,又称为协议族(family)。常用的协议族有,AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。
type:指定socket类型。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等(socket的类型有哪些?)。
protocol:故名思意,就是指定协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议(这个协议我将会单独开篇讨论!)。

小心:并不是上面的type和protocol能够私行己组建合的,如SOCK_STREAM不得以跟IPPROTO_UDP组合。当protocol为0时,会自行选取type类型对应的默许协议。

当我们调用socket创设一个socket时,再次回到的socket描述字它存在于协议族(address
family,AF_XXX)空间中,但绝非四个切实的地点。假若想要给它赋值三个地方,就非得调用bind()函数,不然就当调用connect()、listen()时系统会自行随机分配一个端口。
3.2、bind()函数

正如上面所说bind()函数把一个地址族中的特定地方赋给socket。例如对应AF_INET、AF_INET6正是把二个ipv4或ipv6地址和端口号组合赋给socket。

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

函数的多少个参数分别为:

sockfd:即socket描述字,它是通过socket()函数创建了,唯一标识一个socket。bind()函数就是将给这个描述字绑定一个名字。
addr:一个const struct sockaddr *指针,指向要绑定给sockfd的协议地址。这个地址结构根据地址创建socket时的地址协议族的不同而不同,如ipv4对应的是: 

struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET */
in_port_t sin_port; /* port in network byte order */
struct in_addr sin_addr; /* internet address */
};

/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};

ipv6对应的是:

struct sockaddr_in6 {
sa_family_t sin6_family; /* AF_INET6 */
in_port_t sin6_port; /* port number */
uint32_t sin6_flowinfo; /* IPv6 flow information */
struct in6_addr sin6_addr; /* IPv6 address */
uint32_t sin6_scope_id; /* Scope ID (new in 2.4) */
};

struct in6_addr {
unsigned char s6_addr[16]; /* IPv6 address */
};

Unix域对应的是:

 

1)网络的7层网络协议

#include <sys/socket.h>

define UNIX_澳门金沙国际,PATH_MAX 108

struct sockaddr_un {
sa_family_t sun_family; /* AF_UNIX */
char sun_path[UNIX_PATH_MAX]; /* pathname */
UNIX互连网通讯,网络编制程序。};

addrlen:对应的是地方的长短。
平凡服务器在起步的时候都会绑定一个强烈的地点(如ip地址+端口号),用于提供劳动,客户就能够由此它来三番五次服务器;而客户端就无须钦点,有系统自动分配一个端口号和自小编的ip地址组合。那正是干吗通平常衣服务器端在listen此前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成二个。

网络字节序与主机字节序

主机字节序就是我们平常说的大端和小端模式:不同的CPU有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序。引用标准的Big-Endian和Little-Endian的定义如下:

  a) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

  b) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

网络字节序:4个字节的32 bit值以下面的次序传输:首先是0~7bit,其次8~15bit,然后16~23bit,最后是24~31bit。这种传输次序称作大端字节序。由于TCP/IP首部中所有的二进制整数在网络中传输时都要求以这种次序,因此它又称作网络字节序。字节序,顾名思义字节的顺序,就是大于一个字节类型的数据在内存中的存放顺序,一个字节的数据没有顺序的问题了。

所以:在将一个地址绑定到socket的时候,请先将主机字节序转换成为网络字节序,而不要假定主机字节序跟网络字节序一样使用的是Big-Endian。由于这个问题曾引发过血案!公司项目代码中由于存在这个问题,导致了很多莫名其妙的问题,所以请谨记对主机字节序不要做任何假定,务必将其转化为网络字节序再赋给socket。

3.3、listen()、connect()函数

假如作为一个服务器,在调用socket()、bind()之后就会调用listen()来监听那几个socket,借使客户端那时调用connect()发出连接请求,服务器端就会吸收到那一个请求。

int listen(int sockfd, int backlog);
int connect(int sockfd, const struct sockaddr *addr, socklen_t
addrlen);

listen函数的率先个参数即为要监听的socket描述字,第三个参数为相应socket能够排队的最亚松森接个数。socket()函数创造的socket暗中认可是一个能动类型的,listen函数将socket变为被动类型的,等待客户的连天请求。

connect函数的首先个参数即为客户端的socket描述字,第①参数为服务器的socket地址,第⑤个参数为socket地址的长短。客户端通过调用connect函数来确立与TCP服务器的连天。
3.4、accept()函数

TCP服务器端依次调用socket()、bind()、listen()之后,就会监听钦定的socket地址了。TCP客户端依次调用socket()、connect()之后就想TCP服务器发送了2个总是请求。TCP服务器监听到这么些请求之后,就会调用accept()函数取接收请求,那样总是就确立好了。之后就足以开首网络I/O操作了,即一般于一般文书的读写I/O操作。

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

accept函数的率先个参数为服务器的socket描述字,第一个参数为指向struct
sockaddr
*的指针,用于重回客户端的协商地址,第5个参数为协商地址的尺寸。假使accpet成功,那么其重临值是由基础自动生成的3个簇新的叙述字,代表与重返客户的TCP连接。
小心:accept的率先个参数为服务器的socket描述字,是服务器起首调用socket()函数生成的,称为监听socket描述字;而accept函数再次来到的是已连接的socket描述字。1个服务器一般一般只是只创立多个监听socket描述字,它在该服务器的生命周期内直接存在。内核为种种由服务器进度接受的客户连接创设了1个已连接socket描述字,当服务器达成了对有些客户的劳动,相应的已一而再socket描述字就被关闭。
3.5、read()、write()等函数

万事具备只欠西风,至此服务器与客户已经济建设立好连接了。能够调用网络I/O进行读写操作了,即实现了网咯中不相同进度之间的通讯!网络I/O操作有上边几组:

read()/write()
recv()/send()
readv()/writev()
recvmsg()/sendmsg()
recvfrom()/sendto()

本人引进应用recvmsg()/sendmsg()函数,那五个函数是最通用的I/O函数,实际上能够把地点的任何函数都替换来那七个函数。它们的宣示如下:

#include 

       ssize_t read(int fd, void *buf, size_t count);
       ssize_t write(int fd, const void *buf, size_t count);

       #include 
       #include 

       ssize_t send(int sockfd, const void *buf, size_t len, int flags);
       ssize_t recv(int sockfd, void *buf, size_t len, int flags);

       ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, socklen_t addrlen);
       ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);

       ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
       ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

read函数是背负从fd中读取内容.当读成功时,read再次来到实际所读的字节数,倘诺回去的值是0表示曾经读到文件的扫尾了,小于0代表现身了错误。要是不当为EINTOdyssey表达读是由刹车引起的,如若是ECONNREST表示互连网连接出了难题。

write函数将buf中的nbytes字节内容写入文件讲述符fd.成功时再次回到写的字节数。战败时再次回到-1,并设置errno变量。
在互联网程序中,当我们向套接字文件讲述符写时有俩种可能。1)write的再次来到值大于0,表示写了一些恐怕是全部的数码。2)重临的值小于0,此时出现了不当。大家要基于错误类型来拍卖。借使不当为EINT奥迪Q7表示在写的时候出现了刹车错误。假设为EPIPE表示互连网连接出现了难点(对方已经关门了连年)。

任何的自小编就不一一介绍这几对I/O函数了,具体参见man文书档案恐怕baidu、谷歌(Google),上边的例证元帅使用到send/recv。
3.6、close()函数

在服务器与客户端建立连接之后,会议及展览开局地读写操作,达成了读写操作就要关闭相应的socket描述字,好比操作完打开的文书要调用fclose关闭打开的文本。

 

ISO依据逻辑划分出来7层互联网协议

 

include

服务器端

#include
#include
#include
#include
#include
#include
#include

#define MAXLINE 4096

int main(int argc, char** argv)
{
    int    listenfd, connfd;
    struct sockaddr_in     servaddr;
    char    buff[4096];
    int     n;

    if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
    printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
    exit(0);
    }

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(6666);

    if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){
    printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
    exit(0);
    }

    if( listen(listenfd, 10) == -1){
    printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
    exit(0);
    }

    printf("======waiting for client's request======\n");
    while(1){
    if( (connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -1){
        printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
        continue;
    }
    n = recv(connfd, buff, MAXLINE, 0);
    buff[n] = '\0';
    printf("recv msg from client: %s\n", buff);
    close(connfd);
    }

    close(listenfd);
}

客户端代码:

客户端

#include
#include
#include
#include
#include
#include
#include

#define MAXLINE 4096

int main(int argc, char** argv)
{
    int    sockfd, n;
    char    recvline[4096], sendline[4096];
    struct sockaddr_in    servaddr;

    if( argc != 2){
    printf("usage: ./client \n");
    exit(0);
    }

    if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
    printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);
    exit(0);
    }

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(6666);
    if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){
    printf("inet_pton error for %s\n",argv[1]);
    exit(0);
    }

    if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){
    printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
    exit(0);
    }

    printf("send msg to server: \n");
    fgets(sendline, 4096, stdin);
    if( send(sockfd, sendline, strlen(sendline), 0) < 0)
    {
    printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
    exit(0);
    }

    close(sockfd);
    exit(0);
}

理所当然下边包车型大巴代码非常粗略,也有许多毛病,那就只是简短的以身作则socket的主题函数使用。其实不管有多复杂的互联网程序,都采纳的这几个基本函数。上边的服务器使用的是迭代方式的,即唯有处理完叁个客户端请求才会去处理下四个客户端的呼吁,那样的服务器处理能力是很弱的,现实中的服务器都亟待有出现处理能力!为了必要出现处理,服务器要求fork()一个新的经过也许线程去处理请求等。
7、动动手

雁过拔毛贰个标题,欢迎大家回帖回答!!!是还是不是掌握Linux下网络编制程序?如熟谙,编写如下程序完结如下效果:

劳务器端:

吸收地址192.168.100.2的客户端音讯,如新闻为“Client
Query”,则打字与印刷“Receive Query”

客户端:

向地点192.168.100.168的劳动器端顺序发送新闻“Client Query test”,“Cleint
Query”,“Client Query Quit”,然后退出。

题材中出现的ip地址能够依照真实景况定。

 

 

Socket编程大家纯熟新闻沟通的股票总值,这互联网中经过之间怎么通讯,如我们每天打开浏览器浏览网页时,浏览器的历程怎么与web服务器通…

 

应用层:和应用程序打交道的,举行多少的竞相

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

二、套接字socket

它是一种可以展开互联网通讯的水源对象,它有二个唯一的标识符,一般称它为socket描述符,跟文件讲述符类似,也得以用read/wrote/close操作。

        int socket(int domain, int type, int protocol);/*    
        功能:创建socket对象
        domain:通信地址类型
            AF_UNIX    / AF_LOCAL :本地进程间通信
            AF_INET    :使用ipv4地址通信    
            AF_INET6:使用ipv6地址通信
        type:
            SOCK_STREAM :数据流协议,TCP面向连接的通信协议
                优点:安全可靠,数据不丢失,但速度慢。
                一般常用于安全性较高的场景
            SOCK_DGRAM    :数据报协议,UDP面向无连接的通信协议
                优点:速度快,数据可能会丢失,安全性和可靠性于TCP相比不高
                一般用于安全性要求不高,但对速度有要求的场景。
        protocol:特殊协议一般不使用,直接写 0*/

准备通讯地点:
主导通讯地方
struct sockaddr
{
  sa_family_t sa_family;
  char sa_data[14];
}

地方通讯地方
struct sockaddr_un
{
  // 通讯地方类型
  sun_family_t sun_family;
  // socket文件的路径
  char sun_path[100];
}
网络通讯地方
struct sockaddr_in
{
  //通讯地址类型
  short int sin_family;
  //端口号
  in_port_t sin_port;
  //ip地址
  struct in_addr sin_addr;
}

准备好的通讯地点平时要将其挟持转换到基本通讯地方才能传给函数使用。

    int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
    //功能:把socket对象与通信地址建立联系


    int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
    //功能:连接通信目标
    //socketaddr:目标地址

表示层:将应用程序中的数据依据规则封装起来。

 

叁 、网络通讯的多少存款和储蓄方式

村办总括机种类数据的储存情势恐怕是多方面,也说不定是小端,网络通讯时需求的是多方面数据,必须把数量转换来大端。

        uint32_t htonl(uint32_t hostlong);
        //功能:把32位的主机字节序转换成32位的网络字节序

           uint16_t htons(uint16_t hostshort);
        //功能:把16位的主机字节序转换成16位的网络字节序

           uint32_t ntohl(uint32_t netlong);
        //功能:把32为网络字节序转换成32位的主机字节序

           uint16_t ntohs(uint16_t netshort);
        //功能:把16为网络字节序转换成16位的主机字节序

生成端口号
  端口号正是2个16为的无符号整数

uint16_t htons(uint16_t hostshort);

生成ip地址

        in_addr_t inet_addr(const char *cp);
        //功能:把点分十进制的字符串ip地址转换成32位的无符号整数

        char *inet_ntoa(struct in_addr in);
        //功能:把32位的网络字节序的ip地址转换成点分十进制的字符串ip地址

会话层:聊天,对话的情趣,控制会话的上三宝太监了结等

返回值:
       On success, zero is returned.  On error, -1 is returned, and
errno is set appropriately.

四 、互连网通讯(UDP)

进度A:创制socket对象->准备地址->绑定->接收数据和来时的地方->原路重回数据->关闭socket
进度B:创设socket对象->准备地址->向目的发送数据->接收数据->关闭socket

当socket对象被全体停歇后,会在根本中停留一段时间(给3个重新连接的空子),假使再利用同样的ip地址和端口号时就会失利(延时闭馆)

    ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
    //功能:接收数据并获取发送端的地址
    //addrlen:是参数,要得到的src_addr的长度

    ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);    
    //功能:发送数据到指定的目标

传输层:用于数据交换的通道

 

伍 、网络通讯(TCP)

面向连接的网络通讯,在通讯进程中随时保持一连,那种通讯情势接近与打电话,能保险安全可信、数据不丢掉,但与UDP相比较传输速度略低。

进度A:创立socket->准备地址->绑定->监听(设置队列长度)->等待连接->通讯->关闭。
进程B;创立socket->准备地址->连接->通讯->关闭

    int listen(int sockfd, int backlog);
    //功能:设置socket对象最大的排队数量

    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);     
    //功能:等待其他主机与当前socket建立连接关系。    
    //返回值:建立连接的描述符,此后通信都用此描述符    

    int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
    //功能:连接通信目标
    //socketaddr:目标地址

    ssize_t recv(int sockfd, void *buf, size_t len, int flags);
    //功能:网络通信专用的数据接收    
    //flag: 0  阻塞
    //      1  不阻塞
    //返回值:-1 时,说明连接断开,此时应该结束循环

    ssize_t send(int sockfd, const void *buf, size_t len, int flags);
    //功能:网络通信专用的数据发送
    //返回值:-1 时,说明连接断开    ,此时应该结束循环

 

网络层:通超过实际际的互连网传送数据

描述:

数量链路层:对现实的音信实行编码转换等等。

When a socket is created with socket(), it exists in a name space
(address family) but has no address assigned to it.bind() assigns
the address specified to by addr to the socket  referred  to  by
 the  file  descriptor  sockfd.addrlen specifies the size,
in bytes, of the address structure pointed to by addr.
 Traditionally, this operation is called “assigning a name to a socket”.

物理层:路由器和交流机等

 

2)常见的磋商

 

TCP 传输控制协议,面向连接的商谈

sockfd,即socket描述字,它是透过socket()函数创造,唯一标识一个socket。bind()函数正是将给那个描述字绑定一个名字。

UDP 用户数量报业协会议 ,面向无连接的情商

 

IP  网络协议 ,音信传送机制

addr,一个const struct sockaddr
*指南针,指向要绑定给sockfd的说道地址。这么些地方结构遵照地点创造socket时的地点协议族的分歧而不一致,

3)IP地址

 

IP地址是Internet中绝无仅有的地方标识,一般都以3个叁13人的整数(IPV4),也有1二十多少人整数(ipv6)

ipv4对应的是:

将ip地址中的每贰个字节转换为十进制,选取.隔断,那种IP地址的表示方法叫做:点分十进制表示法

struct sockaddr_in {

IP地址分为互连网号和主机号,将ip地址分为以下四类地址:

    sa_family_t    sin_family; /* address family: AF_INET */

A类:0 + 7人网络地址 + 2二人本土地址

    in_port_t      sin_port;   /* port in network byte order */

B类:10 +12人互连网地址 +十几个人地点地址

    struct in_addr sin_addr;   /* internet address */

C类:110+21为网络地址 +8个人地点地址

};

D类:1110+二十八位多播地址

 

子网掩码是运用点分十进制表示法进行表示,首要用以指名一个IP地址中如何位表示互联网地址,以及怎么样位表示主机地址,不可能独立行使,必须和IP地址搭配使用。

/* Internet address. */

如:IP地址:192.168.182.48

struct in_addr {

子网掩码:255.255.255.0  &

    uint32_t       s_addr;     /* address in network byte order */


};

192.168.182网络地址

 

在那之中48象征主机号

 

能够看清七个差异的IP地址是不是在同三个子网中

ipv6对应的是: 

MAC地址:电脑上的网卡地址,物理地址

struct sockaddr_in6 { 

MAC地址也正是情理地址,也正是网卡的地方,能够由此绑定Mac地址来界定上网的设施

    sa_family_t     sin6_family;   /* AF_INET6 */ 

4)端口号

    in_port_t       sin6_port;     /* port number */ 

IP地址能够一定具体的主机,端口号能够用来固定具体的某部进度

    uint32_t        sin6_flowinfo; /* IPv6 flow information */ 

端口号是unsigned short类型,范围是 : 0 – 65535,个中0 –
1024的端口号一般被系统占用,比如:HTTP:80 FTP:21

    struct in6_addr sin6_addr;     /* IPv6 address */ 

如:

    uint32_t        sin6_scope_id; /* Scope ID (new in 2.4) */ 

0x12345678

};

=> 依照内存地址从低到高顺序存放:

 

0x12    0x34   0x56   0x78

struct in6_addr { 

不及内部存款和储蓄器地址存放高位数据:大端系统

    unsigned char   s6_addr[16];   /* IPv6 address */ 

没有内部存款和储蓄器地址存放低位数据:小端系统

};

字节序只要有三种:互连网字节序 和 主机字节序

 

主机字节序一般代表最近主机的字节顺序

 

网络字节序一般代表差别主机之间的集合字节序

Unix域对应的是: 

2.0

#define UNIX_PATH_MAX    108

使用socket进行通讯,soket -套接字,实际上就是二个逻辑通讯载体

 

2.1一对一通讯的模子

struct sockaddr_un { 

劳务器端:

    sa_family_t sun_family;               /* AF_UNIX */ 

1)创建socket,使用socket函数

    char        sun_path[UNIX_PATH_MAX];  /* pathname */ 

2)准备1个通讯地方,使用结构体类型

};

3)将socket和通讯地点举办绑定,使用bind函数

 

4)举行通讯,使用read/write函数

常常服务器在开发银行的时候都会绑定1个精通的地方(如ip地址+端口号),用于提供服务,客户就能够通过它来连接服务器;而客户端就不要钦赐,由系统活动分配3个端口号和笔者的ip地址组合。那正是干什么平时服务器端在listen此前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成3个。

5)关闭socket,使用close函数

 

客户端:

在套接口中,贰个套接字只是用户程序与根本交互音信的要点,它自个儿没有太多的消息,也尚无互连网协议地址和端口号等信息,在拓展互联网通讯的时候,必须把2个套接字与多少个地址相关联,这一个历程正是地点绑定的进度。许多时候内核会为我们自行绑定2个地方,然则有时用户大概必要团结来形成那些绑定的长河,以满意实际使用的要求,最卓越的景色是一个服务器进度要求绑定二个分明的地点或端口以伺机客户来连接。这几个事由bind的函数完结。

1)创建socket,使用socket函数

 

2)准备一个通讯地点,使用结构体类型

bind函数并不是连续供给调用的,唯有用户进度想与1个切实的地点或端口相关联的时候才须要调用那些函数。假使用户进度没有这几个要求,那么程序能够借助内核的电动的选址机制来形成机关地址选用,而不须要调用bind的函数,同时也幸免不供给的复杂度。在形似意况下,对于服务器进度难点亟待调用bind函数,对于客户进程则不要求调用bind函数。

3)将socket和通讯地方实行连接,使用connect函数

 

4)实行通讯,使用read/write函数

5)关闭socket,使用close函数

2.2 相关函数的牵线1)socket函数

int socket(int domain,int type,int protocol)

首先个参数:域/协议簇 AF_UNIX AF_LOCAL —-本地通讯

AF_INET –使用IPV4拓展通信

AF_INET6 –使用IPV6进展通讯

第三个参数:钦定协议

SOCK_STREAM –使用数据流的样式通讯,TCP协议

SOCK_DGRAM –使用数据报的款式通讯,UDP协议

其三个参数:钦赐越发的商谈,直接给0

再次回到值:成功会回去文件描述符,战败会回去-1

函数效能:创立用于调换的端点,通讯载体

2)bind函数

int bind(int sockfd,const struct sockaddr *addr,socklen_t
addrlen_);

先是个参数:socket描述符

其次个参数:准备的通讯地点

其八个参数:通讯地方的高低

重临值:成功再次来到0,失败再次回到-1

函数成效:将准备的通讯地方和sockt实行绑定

3)准备的通信地方类型

//a 通用的通讯地址s

struct sockaddr{

sa_family_t sa_family;//域,协议簇

char sa_data[14];//地址

};

只顾:此结构体一般很少直接行使,而大多数都以作为函数的参数去行使

//b 本地通讯的布局体类型#include

struct sockaddr_un

{  

sa_family sun_family;//协议簇 

char sun_path[];//socket文件的路线};

//c 互连网通讯的布局体类型

struct sockaddr_in

{

  sa_family_t sin_family;//协议簇

AF_INETin_PORT_T sin_port;//端口号

struct in_addr sin_addr://ip地址}

struct in_addr

{

in_addr_t s_addr;//ip地}

4)connect函数

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

函数的功能相近于bind函数

5)htons函数#includeuint32_t htonl(uint32_t hostlong);

unit32_t ntohl(uint32_t netlong);

unit16_t ntohs(uint16_t netshort);

unit16_t htons(uint16_t hostshort);

成效:htons函数表示将short类型参数的主机字节序,转换为互联网字节序,通过重临值重返转换之后的结果

6)inet_addr函数

in_addr_t inet_addr(cons char *cp)

作用:将参数内定的点分十进制方式的ip地址转换网络字节序的平头地址


2.3依据TCP通讯模型

劳动器端:

1)创建socket,使用socket函数,SOCK_STREAM

2)准备通讯地方,struct sockaddr_in结构体

3)使用绑定,使用bind函数

4)监听,使用listen函数

5)接收客户端的连天请求,使用accept函数

6)实行通讯,使用read/write函数

7)关闭socket,使用close函数

客户端:

1)创建socket

2)准备通讯地点

3)进行一而再

4)举行通讯

5)关闭socket

2.4 相关函数

1)listen函数

int listen(int sockfd,int backlog);

首先个参数:socket描述符

其次个参数:允许访问的最奥斯汀接数,即将连接的连串最大值

再次回到值:成功重返0,退步重返-1

成效:监听socket上的连接请求

2)accept函数

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

第一个参数:sockt描述符

其次个参数:用于保存所承受的客户端的地点

其多少个参数:地址的高低

再次回到值:成功再次回到新的文本描述符,战败重回-1

函数效用:响应客户端的总是请求

留神:使用socket函数创立的叙述符首要用来等待客户端的连天,不参预新闻的相互,而accept函数再次来到的讲述符主要用于针对当前客户端的新闻交互通道

3)inet_ntoa函数

char *inet_ntoa(struct in_addr in);

效果:将网络通讯结构体中的第6个成功类型的ip地址 转换 字符串格局的ip地址


UDP

1.1概念

TCP 传输控制协议 ,面向连接的商事

UCP 用户数量报业协会议 非面向连接的磋商

1.2区别

1)TCP是一种面向连接的商议,在通信的全程保持接二连三

可取:能够保障数据的完整性和安全性以及准确性,并且能够重发一切数据

症结:服务器压力相比大,能源占用率比较高

2)UDP是一种非面向连接的合计,在发送数据时连一下,不包吃全程连接

优点是:服务器压力比较小,能源占用率比较低

症结是:不保险数据的安全性和完整性以及准确性

1.3 基于UDP通讯的模型:

服务器:

1)创建socket,使用socket函数

2)准备通讯地方,使用struct sockaddr_in结构体

3)绑定socket和通讯地方,使用bind函数

4)通信,使用read/write/sendto/recvfrom函数

5)关闭socket函数,使用close函数

客户端:

1)创建socket,使用socket函数

2)准备通讯地方,使用struct sockaddr_in结构体

3)举办通讯,使用read/write/recvfrom/sendto函数

4)关闭socket,使用close函数

1.4有关函数的牵线1)sendto函数

ssize_t send(int sockfd,const voif *buf,size_t len,int flags);

ssize_t sendto(int sockfd,const void *buf,size_t len,int flags,const
struct sockaddr *dest_addr,socklen_t addrlen);

先是个参数:socket描述符

其次个参数:将要发送的数码的首地址

其多个参数:发送的多寡大小

第八个参数:发送的办法,私下认可给0

第④个参数:发送到的对象地址

第伍个参数:指标地址的大大小小

重临值:成功再次来到发送的数量大小,败北重回-1

函数功用:向内定的靶子地址发送数据

只顾:send函数相对于sendto少了指标地址参数,一般用于tcp通信中

2)recvfrom函数

ssize_t recv(int sockfd,void *buf,size_t len,int flags);

ssize_t recvfrom(int sockfd,void *buf,size_t len,int flags,struct
sockaddr *src_addr,socklen_t *addrlen);

第二个参数:socket描述符

第3个参数:存放数据的缓冲区首地址

其七个参数:读取的数量大小

第八个参数:暗中同意给0即可

第陆个参数:存放客户端地址音讯的

第伍个参数:客户端地址的大小

重返值:成功重返读取的数码大小,退步重返-1

函数成效:接受钦定的音信

相关文章