(四)linux网络编程
一、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网络编程的更多相关文章
- Linux网络编程入门 (转载)
(一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...
- [转] - Linux网络编程 -- 网络知识介绍
(一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...
- 【转】Linux网络编程入门
(一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...
- 《转》Linux网络编程入门
原地址:http://www.cnblogs.com/duzouzhe/archive/2009/06/19/1506699.html (一)Linux网络编程--网络知识介绍 Linux网络编程-- ...
- Linux网络编程入门
(一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...
- Linux网络编程(四)
在linux网络编程[1-3]中,我们编写的网络程序仅仅是为了了解网络编程的基本步骤,实际应用当中的网络程序并不会用那样的.首先,如果服务器需要处理高并发访问,通常不会使用linux网络编程(三)中那 ...
- 【linux草鞋应用编程系列】_5_ Linux网络编程
一.网络通信简介 第一部分内容,暂时没法描述,内容实在太多,待后续专门的系列文章. 二.linux网络通信 在linux中继承了Unix下“一切皆文件”的思想, 在linux中要实现网 ...
- Linux 网络编程(IO模型)
针对linux 操作系统的5类IO模型,阻塞式.非阻塞式.多路复用.信号驱动和异步IO进行整理,参考<linux网络编程>及相关网络资料. 阻塞模式 在socket编程(如下图)中调用如下 ...
- Linux网络编程&内核学习
c语言: 基础篇 1.<写给大家看的C语言书(第2版)> 原书名: Absolute Beginner's Guide to C (2nd Edition) 原出版社: Sams 作者: ...
随机推荐
- SlickGrid example 2: 按想要的风格展示列
先上效果图. 代码: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http:// ...
- 20150625_Andriod_02_ListView2_多条目显示_选中
android listview 参考地址: http://www.cnblogs.com/zhengbeibei/archive/2013/05/14/3078805.html http://xy ...
- JAVA基础知识之IO——Java IO体系及常用类
Java IO体系 个人觉得可以用"字节流操作类和字符流操作类组成了Java IO体系"来高度概括Java IO体系. 借用几张网络图片来说明(图片来自 http://blog.c ...
- Collection的toArray()使用上需要注意的地方
转载:http://llade.iteye.com/blog/199818 Collection在很多情况下需要转换为数组来处理(很多接口方法都使用array作为参数). Collection的toA ...
- ..在lua中运用
..连接两个字符串 th> a="hello" th> b="world" th> print(a..b) helloworld th> ...
- 修改idea的运行内存
1.如果本地的jdk是32位的,那么最大的内存只能支持到1024 2.测试jdk位数 public class Test { public static void main(String[] args ...
- DBCP连接Oracle,数据库重启后现OALL8 is in an inconsistent state异常
最近,DBCP连接Oracle,数据库重启后现OALL8 is in an inconsistent state异常. 版本说明 commons-dbcp-1.4.jar commons-pool-1 ...
- Android 4.4之后删除短信进行处理
android 4.4删除短信 android 4.4之后非默认的短信应用已经没有办法删除短信了.像以前那样用如下方法是不会没法删除短信的(即使在xml中配置了短信的读写权限),同时也不会有报错或其他 ...
- android“设置”里的版本号
在文件 packages/apps/Settings/src/com/android/settings/DeviceInfoSettings.java 中 setStringSummary(" ...
- 开机logo切换逻辑深入研究
增加暗码命令切换开关机logo功能 u-boot logo显示原理: 1.----Little Kernel会在platform_early_init阶段首先会获取lcm params,其工作流 程就 ...