一、CS架构,BS架构

(1)CS架构介绍(client server,客户端服务器架构),例如:qq、360网盘
(2)BS架构介绍(broswer server,浏览器服务器架构)例如:浏览器

二、TCP协议学习1

1、关于TCP理解的重点
(1)TCP协议工作在传输层,对上服务socket接口,对下调用IP层
(2)TCP协议面向连接,通信前必须先3次握手建立连接关系后才能开始通信。
(3)TCP协议提供可靠传输,不怕丢包、乱序等。
2、TCP如何保证可靠传输
(1)TCP在传输有效信息前要求通信双方必须先握手,建立连接才能通信
(2)TCP的接收方收到数据包后会ack给发送方,若发送方未收到ack会丢包重传
(3)TCP的有效数据内容会附带校验,以防止内容在传递过程中损坏
(4)TCP会根据网络带宽来自动调节适配速率(滑动窗口技术),如果接收方接收压力很小,发送方便会慢慢提高发送速率;相反接收方压力大,发送方会慢慢讲地发送速率
(5)发送方会给各分割报文编号,接收方会校验编号,一旦顺序错误即会重传。

三、TCP协议的学习2

1、TCP的三次握手

(1)建立连接需要三次握手
(2)建立连接的条件:服务器listen时客户端主动发起connect
2、TCP的四次握手
(3)关闭连接需要四次握手
(4)服务器或者客户端都可以主动发起关闭

注:这些握手协议已经封装在TCP协议内部,socket编程接口平时不用管
3、基于TCP通信的服务模式
(1)具有公网IP地址的服务器(或者使用动态IP地址映射技术)
(2)服务器端socket、bind、listen后处于监听状态
(3)客户端socket后,直接connect去发起连接。
(4)服务器收到并同意客户端接入后会建立TCP连接,然后双方开始收发数据,收发时是双向的,而且双方均可发起
(5)双方均可发起关闭连接
4、常见的使用了TCP协议的网络应用
(1)http(也是一个协议,纯传文件,文本信息)、ftp
(2)QQ服务器
(3)mail服务器

四、socket编程接口介绍

表示IP地址数据结构都定义在 /usr/include/netinet/in.h下,我们在linux下输入vim /usr/include/netinet/in.h便可查看in.h下定义的结构体

1、建立连接
(1)socket。socket函数类似于open,用来打开一个网络连接,如果成功则返回一个网络文件描述符(int类型),之后我们操作这个网络连接都通过这个网络文件描述符。

  int socket(int domain,int type,int protocol) //socket函数非常类似于open函数,socket函数是用来发开一个网络的,如果成功就会返回一个int型数据,网络文件描述符。之后我们操作这个网络都通过这个网络文件描述符。

  dimain:域,网络域,网络地址范围(IPV4或IPV6等)

  type:指定类型:SOCK_STREAM(TCP网络)、SOCK_DGRAM(UDP)、SOCK_SEQPACKET

  protocol:指定协议,如果指定0,表示使用默认的协议
(2)bind函数

  int bind(int socket,const struct *address,socklen_t address_len);

  函数功能及作用:把本地的IP地址和我们的socket绑定起来,也就是第一个参数int socket,

  const struct  sockaddr *address:struct sockaddr,这个结构体是网络编程接口中用来表示一个IP地址的,注意这个IP地址是不区分IPv4和IPv6的(或者说是兼容IPv4和IPv6的)

  address_len:表示IP地址的长度  

(3)listen函数

  int listen(int socket,int backlog)

  int socket:socket接口,和上面一样

  int backlog:表示我们可以同时接收几个,设置监听队列长度。

对于服务器来说只要调用soclet、bind、listen函数就可以进入监听状态了,客户端那边调用socket函数打开文件描述符,然后调用connect去连接

(4)connect

  int connect(int socket,const struct sockaddress *address,socklen_t address_len);

  要连那个服务器,就用那个address,调用connect函数去连接起来。自己的IP地址会自动得放到发送报文里去。这个函数是兼容IPV4和IPV6的,因为struct suckaddress它是兼容IPV4和IPV6的。

3、发送和接收

TCP层是不管谁发谁收的,在应用层实现。

(1)send和write   在网络上发送,类似写文件;接收,类似于读文件。

socket和write函数很想,返回值几乎是一模一样的。ssize_t write(int fildes,const void *buf,size_t nbyte),我们调用write函数写就可以把要写的内容发出去。

send函数封装:ssize_t send(int socket,const void *buffer,size_t length,int flags),send比write就多一个flags,不考虑这个讲flags设置为0,那就和write是一模一样的。我们可以设置flags一些值:MSG_EOR(一个记录信息的一个结尾,表示我们一个信息就要完了),MSG_OOB(带外数据,即非正式数据,正常通信时是没有的,在一些特殊协议里会有),因此send在一些特殊协议我们才会用到flags,正常协议用不到的,正常通信设置flags为0,和write就一样
(2)recv和read

recv,read和send,write也是类比一样。不过他们是接收

recv函数封装:ssize_t recv(int socket,void *buffer,size_t length,int flags);
4、辅助性函数

辅助性函数主要是进行一些IP地址转换的,为什么要进行IP地址转换呢,IP地址有两种形式,一种是点分十进制的形式即192.32.44.5,一种是32位二进制的形式也就是int类型,点分十进制比较符合人们的观看习惯;而二进制格式,更适合机器编程进行封装,操作。因此我们需要在这两种IP地址之间进行可靠的转换,而转换是由封装好的函数实现的。如下所示:

(1)inet_aton、inet_ntoa、inet_addr

inet_aton:将一个字符串IP地址转换为一个32位的网络序列IP地址

int inet_aton(const char *cp, struct in_addr *inp);

inet_aton函数接受两个参数。参数描述如下:
1 输入参数string包含ASCII表示的IP地址。
2 输出参数addr是将要用新的IP地址更新的结构。

inet_ntoa:将网络地址转换成“.”点隔的字符串格式

int inet_aton(const char *cp, struct in_addr *inp);

inet_addr():的功能是将一个点分十进制的IP转换成一个长整数型数(u_long类型)

in_addr inet_addr(const char *cp);

这三个尽量都少使用,没下面好,其实他们和下面两个功能都一致,都没什么缺陷,唯一缺陷是他们不支持IPV6,下面支持。
(2)inet_ntop、inet_pton

这两个现在阶段变成最好使用,上面三个尽量少使用,这两个程序既支持IPV4又支持IPV6,现在我们下代码肯定要用inet_ntop和inet_pton函数

inet_ntop:将32为二进制IP地址转换为点分十进制的形式。

inet_pton:将点分十进制的形式转换为32位二进制的形式。

我们记忆这个比较好记。ntop即n(网络)-to-p(字符串),网络层使用的是32位二进制,因此是32位二进制IP地址转换为点分十进制的形式,pton相反

5、表示IP地址相关数据结构
(1)都定义在 netinet/in.h
(2)struct sockaddr,这个结构体是网络编程接口中用来表示一个IP地址的,注意这个IP地址是不区分IPv4和IPv6的(或者说是兼容IPv4和IPv6的)
(3)

typedef uint32_t in_addr_t; 网络内部用来表示IP地址的类型

struct in_addr
{
  in_addr_t s_addr;
};
(5)

struct sockaddr_in
{
  __SOCKADDR_COMMON (sin_);
  in_port_t sin_port; /* Port number. */
  struct in_addr sin_addr; /* Internet address. */

  /* Pad to size of `struct sockaddr'. */
  unsigned char sin_zero[sizeof (struct sockaddr) -
  __SOCKADDR_COMMON_SIZE -
  sizeof (in_port_t) -
  sizeof (struct in_addr)];
};
(6)struct sockaddr 这个结构体是linux的网络编程接口中用来表示IP地址的标准结构体,bind、connect等函数中都需要这个结构体,这个结构体是兼容IPV4和IPV6的。在实际编程中这个结构体会被一个struct sockaddr_in(IPV4)或者一个struct sockaddr_in6(IPV6)所填充。sockaddr这个结构体是兼容struct sockaddr_in和struct sockaddr_in6的

6、IP地址格式转换函数实践

(1)inet_addr函数:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

in_addr_t inet_addr(const char *cp); 表示将一个十进制的字符串IP地址,转换为机器可是别的in_addr_t(uint32_t)格式。

示例代码如下:

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> #define IPADDR "192.168.1.103" int main(void)
{
in_addr_t addr = ; addr = inet_addr(IPADDR);
printf("addr = 0x%x.\n",addr); //0x6701a8c0 0x67:103、0x01:1、0xa8:168、0xc0:192 return ;
}

网络字节序默认是大端模式,如果是大端模式直接带进去参数就好了,如果是小端模式,要先转换为大端模式,然后再往进传参数。在网络上只允许使用大端模式,不允许小端模式。inet_addr这个函数可以可以检测当前cpu是大端模式还是小端模式,函数内部做了转换了。所以我们不用管大小端,只管他是大端模式就好了。

不过inet_addr这个函数现在一般不用,因为他只适合IPV4网络,不适合IPV6网络。

(2)inet_pton

#include <arpa/inet.h>

int inet_pton(int af, const char *src, void *dst);

这里我们要知道:

int af:表示是选择是IPV4还是IPV6,IPV4参数:AF_INET  IPV6参数:AF_INET6;

const char *src:表示源十进制字符串IP地址,例如"192.168.1.1"

void *dst:表示转出的,32位二进制IP地址,他的传参类型根据IPV4和IPV6有所不同,IPV4传的是:struct  in_addr 类型参数,IPV6传的是:struct in6_addr类型参数。我们还要注意in_addr和in6_addr这两个结构体的组成,如下所示:

typedef uint32_t in_addr_t;
struct in_addr
{
  in_addr_t s_addr;
};

可以看出in_addr这个结构体里面只有一个成员为s_addr,这个成员的类型为in_addr_t即uint32_t类型。

struct in6_addr
{
union
{
uint8_t __u6_addr8[];
#if defined __USE_MISC || defined __USE_GNU
uint16_t __u6_addr16[];
uint32_t __u6_addr32[];
#endif
} __in6_u;
#define s6_addr __in6_u.__u6_addr8
#if defined __USE_MISC || defined __USE_GNU
# define s6_addr16 __in6_u.__u6_addr16
# define s6_addr32 __in6_u.__u6_addr32
#endif
};

inet_pton函数返回值为一个int类型数据,表示转换是否完成,1表示转换成功,0表示转换不成功。

下面写一个IPV4的调用inet_pton函数转换IP地址函数:

 #include <stdio.h>
#include <arpa/inet.h> #define IPADDRESS "192.168.100.160"
int main(void)
{
struct in_addr sAddr = {};
int ulText;
if(ulText)
{
ulText = inet_pton(AF_INET,IPADDRESS, &sAddr);
}
printf("ulText = %d\nsAddr = 0x%x\n",ulText,sAddr.s_addr); return ;
}

(3)inet_ntop函数

#include <arpa/inet.h>

const char *inet_ntop(int af, const void *src,char *dst, socklen_t size);

int af:表示IPV4或者IPV6网络;

const void *src:表示待转换二进制IP地址;

char *dst:表示转换后的十进制字符串IP地址;

socklen_t size:表示转换后的十进制字符串IP地址的长度。

示例代码如下:

#include<stdio.h>
#include <arpa/inet.h> int main(void)
{
struct in_addr addr = {};
char ucBuff[] = {}; addr.s_addr = 0x6601a8c0;
inet_ntop(AF_INET,&addr,ucBuff,sizeof(ucBuff)); printf("IP:%s\n",ucBuff); return ;
}

(四)linux网络编程的更多相关文章

  1. Linux网络编程入门 (转载)

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  2. [转] - Linux网络编程 -- 网络知识介绍

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  3. 【转】Linux网络编程入门

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  4. 《转》Linux网络编程入门

    原地址:http://www.cnblogs.com/duzouzhe/archive/2009/06/19/1506699.html (一)Linux网络编程--网络知识介绍 Linux网络编程-- ...

  5. Linux网络编程入门

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  6. Linux网络编程(四)

    在linux网络编程[1-3]中,我们编写的网络程序仅仅是为了了解网络编程的基本步骤,实际应用当中的网络程序并不会用那样的.首先,如果服务器需要处理高并发访问,通常不会使用linux网络编程(三)中那 ...

  7. 【linux草鞋应用编程系列】_5_ Linux网络编程

    一.网络通信简介   第一部分内容,暂时没法描述,内容实在太多,待后续专门的系列文章.   二.linux网络通信     在linux中继承了Unix下“一切皆文件”的思想, 在linux中要实现网 ...

  8. Linux 网络编程(IO模型)

    针对linux 操作系统的5类IO模型,阻塞式.非阻塞式.多路复用.信号驱动和异步IO进行整理,参考<linux网络编程>及相关网络资料. 阻塞模式 在socket编程(如下图)中调用如下 ...

  9. Linux网络编程&内核学习

    c语言: 基础篇 1.<写给大家看的C语言书(第2版)> 原书名: Absolute Beginner's Guide to C (2nd Edition) 原出版社: Sams 作者: ...

随机推荐

  1. 【转】探索C++的秘密之详解extern

    本文转自:http://i.cnblogs.com/EditPosts.aspx?opt=1 时常在cpp的代码之中看到这样的代码: #ifdef __cplusplus extern "C ...

  2. COM技术の接口

    什么是接口 DLL的接口可以理解为其导出的那些函数,C++类的接口则是该类的一个成员函数集. 对于COM来说,接口是一个包含一个函数指针数组的内存结构,每一个数组元素包含的是一个由组件所实现的函数的地 ...

  3. C# 中var as is 泛型集合

    一.var var:万能变量类型,跟JS一样. 二.as:非强转类型. 强转类型:一般在变量前面加:(所需类型).如果转换失败,系统就会报错,如果用as,就不会报错,转换失败的话,就会返回null, ...

  4. 求解数组环中最大子数组和的问题(java)

    //石家庄铁道大学 信1405-1 班 唐炳辉 在上一次作业中,对于普通数组的最大子数组的求解问题的基础上,将普通的数组变成一个首尾相接的环,求这个环的最大子数组.类似的,只要改变普通数组的数组位置, ...

  5. Python 字符串、元组、字典转换成列表

  6. 【转载】ODBC, OLEDB, ADO, ADO.Net的演化简史

    原文:ODBC, OLEDB, ADO, ADO.Net的演化简史 1.演变历史 它们是按照这个时间先后的顺序逐步出现的,史前->ODBC->OLEDB->ADO->ADO.N ...

  7. 51NOD1433] 0和5(数论,规律)

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1433 数论关于3的倍数有一个推论,就是能被9整除的数的各位和都 ...

  8. 5.5.3使用terminfo功能标志

    当使用terminfo时,需要做的第一件事就是调用函数setupterm来设置终端类型.这将为当前的终端类型初始化一个TERMINAL结构.然后,你就可以查看当前终端的功能标志并使用他们的功能了. # ...

  9. Monocular Vision

    Monocular Vision: a condition in which one eye is blind, seeing with only one eye Binocular Vision:  ...

  10. Fiddler界面详解

    Statistics 页签 完整页签如下图: Statistics 页签显示当前用户选择的 Sessions 的汇总信息,包括:选择的 Sessions 总数.发送字节数.接收字节数.响应类型的汇总表 ...