C语言高级编程——网络编程技术
了解什么是网络编程
熟悉七层网络模型
熟悉网络开发中使用到的函数
掌握TCP协议类程序开发
掌握UDP协议类程序开发
计算机本身是不会进行网络通信的,所以要想使通过软件进行网络通信,必须制定相应的规则,其中就包括网络架构、通讯协议、等等。
端口,一个主机中可能会有很多网络通信程序,每一个程序都要使用这个固定ip进行通信,所以端口就是每一个固定程序的id。
TCP (流格式传输控制协议)
UDP(数据包格式传输控制协议)
网络架构
TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能。在因特网协议族中,TCP层是位于IP层之上,应用层之下的中间层。
UDP是User Datagram Protocol的简称,中文名是用户数据报协议,是OSI参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETF RFC 768是UDP的正式规范。UDP在IP报文的协议号是17。
七层网络架构组成:
应用层(Application)
表示层(Presentation)
会话层(Session)
传输层(Transport)
网络层(Network)
数据链路层(Data Link)
物理层(Physical)
物理层是硬件。应用层是和硬件层相隔最远的--它是用户和网络交互的地方。
首先是简单的一个:socket描述符。它是下面的类型:int,仅仅是一个常见的int。
需要注意的是:有两种字节排列顺序:重要的字节在前面,或者不重要的字节在前面。前一种叫“网络字节顺序(Network Byte Order)”。有些机器在内部是按照这个顺序储存数据,而另外一些则不然。当要求某数据必须按照NBO顺序,那么就要调用函数(例如htons())来将它从本机字节顺序(Host Byte Order)转换过来。如果没有用到NBO,那么就让它保持本机字节顺序。
网络字节顺序NBO:按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题。
主机字节顺序HBO:不同的机器HBO不相同,与CPU设计有关,不同的CPU有不同的字节序类型。这些字节序是指整数在内存中保存的顺序,这个叫做主机序。
socket函数
bind函数
connect函数
listen函数
accept函数
WSAStartup函数与WSACleanup函数
send函数与recv函数
sendto函数与recvfrom函数
closesocket函数与shutdown函数
SOCKET socket (
int af,
int type,
int protocol );
参数介绍如下:
type:新套接口的类型描述。
protocol:套接口所用的协议。如调用者不想指定,可用0指定,表示缺省。
在使用socket函数进行编程时,需要加入winsock2.h头文件,并且引入ws2_32.lib静态库。
函数原型:
int bind
( SOCKET s,
const struct sockaddr FAR* name,
int namelen );
参数类型:
s:已经创建好的一个套接字句柄。
name:是一个指向sockaddr结构体类型的指针。
namelen:表示sockaddr结构的长度,可以用sizeof函数获得。
本函数用于创建与指定外部端口的连接。s参数指定一个未连接的数据报或流类套接口。如套接口未被捆绑,则系统赋给本地关联一个唯一的值,且设置套接口为已捆绑。
函数原型:
int connect (
SOCKET s,
const struct sockaddr FAR* name,
int namelen
);
参数类型:
s:标识一个未连接socket
name:指向要连接套接字的sockaddr结构体的指针
namelen:sockaddr结构体的字节长度
Listen函数让创建的套接字处于监听状态,主要用于监听连接请求。
函数原型:
int listen (
SOCKET s,
int backlog
);
参数说明:
s一个已绑定未被连接的套接字描述符
backlog连接请求队列的最大长度(一般由2到4)
accept函数主要用于服务器端,一般位于listen函数之后,默认会阻塞进程,直到有一个客户请求连接,建立好连接后,它返回的一个新的套接字socket_new,此后,服务器端即可使用这个新的套接字socket_new与该客户端进行通信,而sock则继续用于监听其他客户端的连接请求。
函数原型:
SOCKET accept (
SOCKET s,
struct sockaddr FAR* addr,
int FAR* addrlen
);
参数说明:
s:套接字句柄,该套接口在listen()后监听连接。
WSAStartup函数完成对Winsock服务的初始化,使用Socket的程序在使用Socket之前必须调用WSAStartup函数。该函数的第一个参数指明程序请求使用的Socket版本,其中高位字节指明副版本、低位字节指明主版本;操作系统利用第二个参数返回请求的Socket的版本信息。
WSACleanup函数用于清理工作,每一次WSAStartup()调用,必须有一个WSACleanup()调用,用于实际的清理工作。此函数没有参数因为它只做清理工作
send函数适用于已连接的数据包或流式套接口发送数据。对于数据报类套接口,必需注意发送数据长度不应超过通讯子网的IP包最大长度。
recv函数同send函数类似,只不过一个用于发送一个用于接收。
Sendto函数用来将数据由指定的socket传给对方主机,由于sendto函数是基于UDP传输协议的所以不用建立连接。
Closesocket函数关闭一个已经建立的套接字。更确切地说,它释放socket建立好的套接字句柄,关闭以后对对套接字的访问均以WSAENOTSOCK错误返回。
shutdown函数用于任何类型的套接口禁止接收、禁止发送或禁止收发。
基于TCP协议的网络通信程序,有一个服务端一个客户端,查看一下一个简单通讯模型。
Tcp通信基本流程:
服务器端-----------------------------------------------客户端
1.创建socket------------------------------------------1.创建socket
2.bind()
3.listen()
4.accept()
等待客户端连接---------------------------------------2.connect()
5.读数据(recv)-------------------------------------3.写数据(send)
6.写数据(send)------------------------------------4.读数据(recv)
7.关闭socket(closesocket())---------------5.关闭socket(closesocket())
基于UDP协议我们做一个聊天室程序,它分为服务端和客户端两个程序。
Udp通信基本流程:
服务器端:-------------------------------------客户端
1.创建socket----------------------------------1.创建socket
2.bind()-------------------------------------2.bind()
3.recvfrom
等待连接---------------------------------------3.sendto()
4.sendto()--------------------------------- 4.recvfrom()
5.关闭socket(closesocket())------5.关闭socket(closesocket())