互联网之移动网络编程复习40P.docx
- 文档编号:18387055
- 上传时间:2023-08-16
- 格式:DOCX
- 页数:31
- 大小:568.31KB
互联网之移动网络编程复习40P.docx
《互联网之移动网络编程复习40P.docx》由会员分享,可在线阅读,更多相关《互联网之移动网络编程复习40P.docx(31页珍藏版)》请在冰点文库上搜索。
互联网之移动网络编程复习40P
1、手机游戏简介及TCP/IP网络编程基础知识
1)常用缩写:
什么叫C/S、B/S、P2P?
C/S(Client客户端/Server服务器)
B/S(Browser浏览器/Server服务器)
P2P(PeertoPeer)
2)TCP/IP网络编程基础知识
OSI(开放系统互连)模型与TCP/IP模型对比
应用层:
该层负责实际的应用程序细节,包括FTPHTTPSMTPTELNET
传输层:
主要为两台主机上的应用程序提供端到端的数据通信。
主要有TCP/UDP两种传输模式。
TCP/IP的核心部分是传输层协议
网络层:
负责主机间数据的路由和网络上数据的存储,有IP/ICMP/ARP/RARP。
为ICMP,TCP,UDP(UserDatagramProtocol用户数据报协议)提供分组发送服务。
链路层(网络接口层):
包括操作系统中的设备驱动程序和计算机中对应的网卡,他们一起处理传输媒介的物理接口细节。
TCP(TransmissionControlProtocol传送控制协议)/IP协议:
实际上就是在物联网上的一组完整的网络协议
(TCP:
提供传输层服务,IP:
提供网络层服务)
2、Socket概述和TCP通信程序设计
1、Socket概述
C/S通信模型——不对称的模型
TCP/IP模型
TCP/IP协议的核心部分是传输层协议(TCP、UDP),网络层协议(IP)和物理接口层,这三层通常是在操作系统内核中实现。
因此用户一般不涉及。
2、什么是套接字/套接口(socket)?
套接字,是支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。
从网络整体来看,它是不同主机上应用程序之间的一个虚拟的接口,具有跨平台特性。
从程序员角度来看,它是应用程序和网络设备的一个接口,特殊的I/O
3、Berkeleysocket和WinSock的不同
1 Berkeleysocket是一个int数据类型,WinSockSock则是SOCKET数据类型
2 WinSock中以SOCKET_ERROR代表出错,BerkeleySocket以-1代表出错
3 WinSock应用必须首先调用WSAStartup()初始化,并在结束前调用WSACleanup()释放资源,而BSDsocket不用。
4 WinSock使用closesocket中止一个连接,而BSDsocket使用close。
4、Socket的分类
字节流套接字(StreamSockets)——面向连接的
数据报套接字(DatagramSockets)——无连接的
原始套接字(RawSockets)——只对Internet协议有效,用于直接访问IP协议
5、不同操作系统中的Socket
——WindowsSocket(Winsock)
——LinuxSocket(BSDSocket)
——MacSocket(BSDSocket)
BSDSocket:
需要使用的头文件——
数据类型:
#include
函数定义:
#include
6、IP地址与端口
如果把IP数据包的投递过程看成是给远方的一位朋友寄一封信,那么IP地址就是这位朋友的所在位置,如:
广州华软学院游戏戏(依靠此信息进行路由)
端口号就是这位朋友的名字(依靠这个信息最终把这封信交付给这位收信)
7、套接字的数据结构:
1 通用的套接字地址结构
structsockaddr{
{
unsignedshortsa_family;//地址家族
charsa_data[14];//14字节协议地址
};
位于sys/socket.h文件中
结构中sa_family为套接字的协议族地址类型,例如对于通常的TCP/IP协议(IPv4),它的值是AF_INET;sa_data中存储着具体的协议地址,不同的协议族有不同的地址格式。
sa_data的存储内容往往是包含地址和端口信息,而仅使用一个变量,所以使用起来不太方便。
2 Sockaddr结构的并列形式
structsockaddr_in{
shortintsin_family;//通信类型
unsignedshortintsin_port;//端口,2bytes
structinaddrsin_addr;//Internet地址,4bytes
unsignedcharsin_zero[8];;
//填充的空白信息,这样就保持整个结构与sockaddr结构的长度相同
};
其中,in_addr结构定义如下:
struct in_addr {
unsignedlong s_addr ;
}
/*s_addr必须是网络字节顺序 Network Byte Order*/
备注:
sockaddr只是一个抽象的概述形式,并不实用。
sockaddr_in更加结合了TCP/IP协议族的特点,易于使用,所以编程中常使用这个结构。
但是:
socket本身所封装的API都是支持sockaddr结构的,所以填充sockaddr_in结构需要强制转换成sockaddr结构,方可作为参数被socket的标准函数所使用。
8、字节顺序
◆主机字节顺序(HostByteOrder)
低位在前,高位在后(little-endian)
基于Intel芯片的机器采取这种存储方式
◆网络字节顺序(NetworkByteOrder)
高位在前,低位在后(big-endian)
sockaddr_in的变量成员(端口和地址)都必须使用网络字节顺序
9、转换字节顺序的函数
10、将IP地址转换为网络字节顺序
inet_addr
unsignedlonginet_addr(constchar*cp);
将需要通信的IP地址转化为整数,并填充sockaddr_in的sin_addr成员
inet_ntoa
char*inet_ntoa(structin_addrin);
例如将0A00A8C0转化为“192.168.3.10”
11、TCP网络通讯编程
●创建一个被动模式(server,服务器)的socket.
●建立应用层的连接
●Client/Server交互
在发送和接收数据之前——
client必须调用connect连接服务器
server必须调用accept接收client的连接
●发送和接收数据.
●关闭连接.
12、网络连接函数:
socket 创建套接字
connect 建立连接
bind 绑定本机端口
listen 监听端口
accept 接受连接
recv,recvfrom 数据接收
send,sendto 数据发送
close,shutdown 关闭套接字
13、TCP客户服务器通信机制
14、基本套接字函数
(1)-socket()
基本套接字函数
(2)-connect()
基本套接字函数
(2)-例子
intfd;/*套接字描述符*/
structsockaddr_insrv;/*套接字地址结构*/
/*创建socket,调用函数socket,语句同前面socket的例子*/
srv.sin_family=AF_INET;/*connect:
AF_INET表示使用Internet地址族*/
srv.sin_port=htons(8000);/*connect:
目标是连向服务器的8000号端口*/
srv.sin_addr.s_addr=inet_addr(“202.38.75.11”);/*connect:
目标服务器的IPAddress是“202.38.75.11”*/
if(connect(fd,(structsockaddr*)&srv,sizeof(srv))<0){
fprintf(stderr,”connecterror!
\n");
exit
(1);
}
基本套接字函数(3)-bind()
基本套接字函数(3)-例子
intfd;/*套接字描述符*/
structsockaddr_insrv;/*套接字地址结构*/
/*创建socket,调用函数socket,语句同前面socket的例子*/
srv.sin_family=AF_INET;/*AF_INET表示使用Internet地址族*/
srv.sin_port=htons(80);/*将socket绑定到80号端口*/
srv.sin_addr.s_addr=htonl(INADDR_ANY);/*bind:
INADDR_ANY表示服务器将接收来自本机上任何一块网卡的客户连接*/
if(bind(fd,(structsockaddr*)&srv,sizeof(srv))<0){
fprintf(stderr,”binderror!
\n");
exit
(1);
}
基本套接字函数(4)-listen()
基本套接字函数(4)-例子
intfd;/*套接字描述符*/
structsockaddr_insrv;/*usedbybind()*/
/*1)createthesocket*/
/*2)bindthesockettoaport*/
if(listen(fd,20)<0){
fprintf(stderr,”listenerror!
\n");
exit
(1);
}
基本套接字函数(5)-accept()
基本套接字函数(5)-例子
structsockaddr_incli;/*usedbyaccept()*/
intnewfd;/*用来存放accept返回的新的套接字*/
intcli_len=sizeof(cli);/*usedbyaccept()*/
/*1)createthesocket*/
/*2)bindthesockettoaport*/
/*3)listenonthesocket*/
newfd=accept(fd,(structsockaddr*)&cli,&cli_len);
if(newfd<0){
fprintf(stderr,"accepterror\n");
exit
(1);
}
cli.sin_addr.s_addr包含了客户的IP地址
cli.sin_port包含了客户的端口数
其他需要用到的函数
intread(intfd,char*buf,intlen);
返回实际接收的缓冲区大小
intwrite(intfd,char*buf,intlen);
返回实际发送的缓冲区大小
intclose(intsockfd);
成功返回0,否则返回-1
recv()函数
intrecv(SOCKETs,
char*bytesToReceive,
intnBytes,
intflags);
✧s是已经连接的Socket
✧bytesToReceive指向用于接收数据的缓冲区的指针
✧nBytes是缓冲区的字节数
✧flags
0,MSG_DONTROUTE,orMSG_OOB
✧当调用成功,recv()返回被接收的字节数;如果返回0,则说明连接已经被关闭;当调用失败,返回SOCKET_ERROR。
注意:
recv()并不保证接收到所有请求的数据。
它实际接收的字节数由返回值指示。
也许需要循环调用recv()来得到需要的结果。
recv()的典型用法
#defineBUFSIZE1024
SOCKETs;
charbuf[BUFSIZE];//缓冲区
intbytesRecv;
//创建socket并连接服务器
//...
bytesRecv=recv(s,buf,BUFSIZE,0);
if(bytesRecv==SOCKET_ERROR)
{
printf("recv()调用错误:
%d",WSAGetLastError());
}
elseif(bytesRecv==0)
{
printf("对方已经关闭连接.");
closesocket(s);
}
else
{
//处理缓冲区的数据
}
send()函数
intsend(SOCKETs,
constchar*bytesToSend,
intnBytes,
intflags);
✧s是已经连接的Socket
✧bytesToSend指向待发送数据缓冲区的指针
✧nBytes是待发送数据的字节数
✧flags指定调用方式。
常用0。
注意:
send()并不保证发送所有请求的数据。
它实际发送的字节数由返回值指示。
也许需要循环调用send()来得到需要的结果。
close()函数
15、BSDsocket与winsocket创建区别
//Berkeley形式
intsocket(intfamily,inttype,intprotocol);
//WinSock形式
SOCKETsocket(intfamily,inttype,intprotocol);
第三周:
UDP网络通讯及其它socket函数
1、无连接UDP协议的Socket调用
client/serverUDP通信
基本套接口函数(7)
与TCP不同的是,UDP在通信时,系统内部不记录套接口地址信息,都是函数中主动以参数的形式指明的.在TCP情况下,客户connect成功后(服务器accept成功后),每次发送接收都只需指定套接口描述符就行了,但是这里每次发送接收都需要额外附加上对方的套接口地址信息.
初始-建立socket
intfd;/*套接口描述符*/
if((fd=socket(AF_INET,SOCK_DGRAM,0))<0){
perror(“socket”);
exit
(1);
}/*建立socket,与TCP类似*/
服务器和客户端bind
服务器和客户端recvfrom
服务器和客户端sendto
2、其它常用socketapi函数
1 gethostname()
2 从域名解析得到IP地址(gethostbyname)
3 inet_ntop及inet_pton
3、阻塞
阻塞模式:
是socket的缺省方式,也是最常用的方式,即调用结果返回之前,函数阻塞,当前线程会被挂起,suspend。
可能造成阻塞的函数有:
connect()、accept()、读写函数、gethostbyname()等。
4、再探send和recv
◆send和recv是socket编程中两个核心的函数。
◆send表示发送数据,其实际上比不是直接将数据发送出去,而是将数据先发送到系统对应的socket的缓冲区,在由系统使用tcpip协议进行发送。
此时send返回的结果只是表明是否成功发送到系统的缓冲区。
◆同样recv函数也是从系统的对应的socket缓冲区读取数据,而该缓冲区中的数据也是由协议保证的。
如果该缓冲区没有数据,将区别对待:
如果对应的socket是阻塞的,则recv工作在阻塞模式,将一直等到缓冲区中有数据才返回,否则会一直挂起。
5、非阻塞模式
◆非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。
◆如果指定非阻塞模式,程序调用可能造成阻塞的函数时,如果会发生阻塞,这些函数返回-1并将errno设置为EAGAIN或EWOULDBLOCK,程序可继续向下运行。
可能阻塞的函数对应的任务完成,则再次调用该函数时就返回0表示运行结束。
第四周:
并发服务器与多进程
1、知识回顾
TCP:
传输控制协议TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。
2、面向连接的C/S程序工作流程(TCP)
服务器端工作流程
使用socket()函数创建服务器端通信套接口
使用bind()函数将创建的套接口与服务器地址绑定
使用listen()函数使服务器套接口做好接收连接请求准备
使用accept()接收来自客户端由connect()函数发出的连接请求
根据连接请求建立连接后,使用send()函数发送数据,或者使用recv()函数接收数据
使用close()函数关闭套接口(可以先用shutdown()函数先关闭读写通道)
客户端程序工作流程
使用socket()函数创建客户端套接口
使用connect()函数发出也服务器建立连接的请求(调用前可以不用bind()端口号,由系统自动完成
连接建立后使用send()函数发送数据,或使用recv()函数接收数据
使用close()函数关闭套接口
3、UDP协议
用户数据报协议(UDP)是ISO参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。
与TCP不同,UDP并不提供对IP协议的可靠机制、流控制以及错误恢复功能等。
由于UDP比较简单,UDP头包含很少的字节,比TCP负载消耗少。
UDP适用于一次只传送少量数据、对可靠性要求不高的应用环境。
提供高效率服务;如果自己完成安全性检查,UDP也可用于大型文件的传输。
4、无连接UDP协议的Socket调用
client/serverUDP通信
5、无连接的C/S程序工作流程(UDP)
无连接的数据报传输服务通信时,客户端与服务器端所使用的函数是类似的,其工作流程如下:
使用socket()函数创建套接口,以确定协议类型
调用bind()函数将创建的套接口与本地地址绑定,确定本地地址和本地端口号
使用sendto()函数发送数据,或者使用recvfrom()函数接收数据
使用close()函数关闭套接口
6、并发服务器
按连接类型分类——
并发无连接服务器
并发连接服务器
按并发技术分类——
多进程
多线程
IO多路复用
7、单进程非阻塞并发服务器
Objective_C常用容器
NSArray 用于对象有序集合(相当于是数组)
NSSet 用于对象无序集合
NSDictionary用于键值映射
以上三种集合类是不可变的(一旦初始化后,就不能改变)
以下是对应的三种可变集合类(这三种可变集合类是对应上面三种集合类的子类):
NSMutableArray NSMutableSet NSMutableDictionary
注:
这些集合类只能收集cocoa对象(NSOjbect对象),如果想保存一些原始的C数据
(例如,int,float,double,BOOL等),则需要将这些原始的C数据封装成NSNumber类型的,NSNumber对象是cocoa对象,可以被保存在集合类中。
8、关于阻塞的问题
阻塞:
是指一个线程执行了一个函数或者系统调用,该函数由于某种原因不能立即完成,因而不能返回调用它的线程,导致线程受控于这个函数而处于等待挂起的状态,线程的这种状态称为阻塞。
9、能引起阻塞的套接字调用
在Berkeley套接字网络编程接口的模型中,套接字的默认行为是阻塞的,具体地说,在一定情况下,有多个操作套接字的系统调用会引起进程阻塞。
(1)accept()
(2)read()、recv()和recvfrom()
(3)write()、send()和sendto()
(4)connect()
(5)select()
(6)close()
10、服务器实现非阻塞套接字设置(fcntl)
1、获取文件的flags:
flags=fcntl(fd,F_GETFL,0);
2、设置文件的flags:
fcntl(fd,F_SETFL,flags);
3、增加文件的某个flags,比如文件是阻塞的,想设置成非阻塞:
flags=fcntl(fd,F_GETFL,0);
flags|=O_NONBLOCK;
fcntl(fd,F_SETFL,flags);
4、取消文件的某个flags,比如文件是非阻塞的,想设置成为阻塞:
flags=fcntl(fd,F_GETFL,0);
flags&=~O_NONBLOCK;
fcntl(fd,F_SETFL,flags);
也可调用ioctl调用实现非阻塞设置
服务器实现非阻塞fcntl例子
intflags;
if((flags=fcntl(socketListen,F_GETFL,0))==-1)
{
perror("fcntlF_GETFLfail:
");
exit
(1);
}
flags|=O_NONBLOCK;
if(fcntl(socketListen,F_SETFL,flags)==-1)
{
perror("fcntlF_SETFLfail:
");
exit
(1);
}
服务器实现非阻塞recv收到消息例子
NSMutableSet*remove=[[NSMutableSetalloc]init];
for(NSNumber*objinsClientSet)
{
charnewMsg[MSGSIZE];
memset(newMsg,0,MSGSIZE);
intintSocket=[objintValue];
//调用recv接收到客户端的消息
intnLen=recv(intSocket,newMsg,MSGSIZE,0);
if(nLen>0){
newMsg[nLen]='\0';
printf("接收到%d:
%s\r\n",intSocket,newMsg);
}
11、多进程并发执行的服务器程序
fork()
函数:
pid_tfork()
功能:
创建一个新的进程.
说明:
本系统调用产生一个新的进程,叫子进程,是调用进程的一个复制品。
调用进程叫父进程,子进程继承了父进程的几乎所有的属性。
返回值:
调用成功则对子进程返回0,对父进程返回子进程号,这也是最方便的区分父子进程的方法.若调用失败则返回-1给父进程,子进程不生成.
利用UNIX操作系统的fork()系统调用,编制多进程并发执行的服务器程序,可以创建子进程。
对每一个客户端,用一个专门的
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 互联网 移动 网络 编程 复习 40
![提示](https://static.bingdoc.com/images/bang_tan.gif)