标签:eof 图片 参数 之间 上进 上传 博客 顺序 进度
??TCP协议是面向连接的协议,它提供了一系列的数据纠错功能,可以保证数据在网络上传输及时、无误给接收方。因此面向连接协议的Socket编程模型应用最为广泛,基于连接协议的服务是设计客户端/服务器应用程序时的标准。编程模型如图所示
模型中,服务器端的处理:
(1)使用socket系统调用,生成一个TCP协议模块与应用程序之间进行通信的套接字;使用bind系统调用指定端口号;
(2)使用bind系统调用指定端口号;
(3)使用listen系统调用,指定连接接收队列的长度,并等待来自客户端的连接请求。
??前三步完成了启动服务器程序的工作。一旦listen监听到有客户端的连接,就调用accept接收连接。
??希望与服务器通信的进程称为客户,客户所运行的计算机环境称为客户端,有时两个概念混用。
??客户端的处理:
(1)使用socket系统调用,打开TCP协议模块与应用程序之间的通信线路;
(2)使用connect系统调用,指定IP地址和端口号,和服务器相应的服务应用程序建立TCP协议的连接请求;
??客户端和服务器程序在建立连接后,使用send和recv调用完成数据的发送和接收工作。等待数据传送结束后,各自调用close关闭套接字。
??使用TCP协议的Socket通信程序包括服务程序和客户程序。
基于C的Socket编程相关函数和数据类型
1.sockadd
和sockaddr_in
结构:
① sockaddr
结构
struct sockaddr
{
unsigned short sa_family; /*地址族,AF_xxx有IPV4与IPV6等*/
char sa_data[14]; /*14字节的协议地址*/
};
sa_family
一般为AF_INET
,表示Internet协议族,如是AF_UNIX
表示UNIX协议簇;sa_data
中包含该socket的IP地址和端口号。
② in_add
结构,用来存储四字节的IP地址
struct in_addr{
unsigned long s_addr;
};
③ sockaddr_in
结构
struct sockaddr_in
{
short int sin_family; /*地址族*/
unsigned short int sin_port; /*端口号*/
struct in_add sin_addr; /*IP地址*/
unsigned char sin_zero[8]; /*填充0以保持与struct sockaddr同样大小*/
};
该结构中sin_zero
使得sockaddr
和sockaddr_in
指针类型相互转换;sin_port
和sin_addr
必须是网络字节顺序,因为它们被封装在包的IP和UDP层,而sin_family
不发送到网络上可以是本机字节顺序。
相关函数
1.socket()
函数
??该函数用于根据指定的地址族、数据类型和协议来分配一个套接字的描述字及其所用的资源。Socket函数原型为:
int socket( int domain , int type , int protocol ) ;
a、 参数domain指定地址描述,一般为AP_INET
;
b、 参数type指定socket类型:SOCK_STREAM
和SOCK_DGRAM
;
c、参数protocol通常为0;
d、 函数返回值为一个整型socket描述符,在bind
函数中调用。
2.bind()
函数
??该函数用于将一个本地地址与一个套接字绑定在一起。
int bind( int sockfd , struct sockadd* my_addr , int addrlen) ;
a、sockfd
:socket描述符,使用socket函数返回值,将该socket与本机上的一个端口相关联。
在设计服务器端程序是需要调用bind函数,以在该端口上监听服务请求;而客户端一般不需要调用bind函数,因为只需知道服务器IP地址,并不关心客户通过哪个端口与服务器建立连接,内核会自动选择一个未被占用的端口供客户端来使用。
b、my_addr
:指向包含本机IP地址及端口号等信息的sockaddr类型的指针。
c、addrlen
:sizeof( struct sockaddr)
的值。
d、bind函数返回值:为-1表示遇到错误,并且errno中包含相应的错误码。
3.connect()
函数
??与远程服务器建立一个TCP连接。
int connect(int sockfd, struct sockaddr* serv_addr, int addrlen);
a、sockfd
:目的服务器的socket描述符。
b、serv_addr
:指向包含目的服务器的IP地址及端口号的指针。
c、addrlen
:sizeof( struct sockaddr)
的值。
d、connect
函数返回值:为-1表示遇到错误,并且errno中包含相应的错误码,进行服务器端程序设计时不需调用connect函数。
4.listen()
函数
??在服务器端程序中,当socket与某一端口绑定后,需要监听该端口,及时处理到达该端口上的服务请求。
int listen(int sockfd, int backlog);
a、sockfd
:Socket系统调用返回的socket描述符。
b、backlog
:指定在请求队列中允许的最大请求数,进入的连接请求将在队列中等待接收backlog
限制了队列中等待服务的请求数目,系统缺省值为20。
c、listen
函数返回值:为-1表示遇到错误,并且errno中包含相应的错误码。
5.accept()
函数
??当某个客户端试图与服务器监听的端口连接时,该连接请求将排队等待服务器用accept
接收它并为其建立一个连接。
int accept(int sockfd, struct sockaddr* addr, int* addrlen);
a、sockfd
:被监听的socket描述符。
b、addr
:sockaddr类型的指针变量,用来存放提出连接请求服务的主机信息。
c、accept
函数返回值:为-1表示遇到错误,并且errno中包含相应的错误码,如果没有错误,accept()
函数返回一个新想socket描述符,供这个新连接来实用,而服务器可以继续在以前的socket上监听,同时可以在新的socket描述符上进行数据发送和数据接收(sent()
和recv()
操作)。
6.sent()
和recv()
函数
??用于在面向连接(TCP)的socket上进行数据传输。
send()
函数原型:
int send(int sockfd, const void* msg, int len, int flags) ;
a、sockfd
:用于传输数据的socket描述符。
b、msg
:是一个指向要发送数据的指针。
c、len
:以字节为单位的数据的长度。
d、flags
:一般情况下置为0。
e、函数返回值:为-1表示遇到错误,并且errno中包含相应的错误码,否则返回所发送数据的总数,该数字可能小于len中所规定的大小。
recv()
函数原型:
int recv(int sockfd, void* buf, int len, unsigned int flags);
a、sockfd
:是接收数据的socket描述符。
b、buf
:是存放接收数据的缓冲区。
c、len
:以字节为单位的缓冲区的长度。
d、flags
:一般情况下置为0。
e、函数返回值:为-1表示遇到错误,并且errno中包含相应的错误码,无错则返回读入的字节数,如果连接被中止,返回0。
7.endto()
和recvfrom()
函数
??这两个函数是利用数据报方式(UDP)进行数据传输。在无连接的数据报socket方式下,由于本地socket并没有与远程机器建立连接,所以在发送数据时应指明目的地址。
sendto()
原型:
int sendto(int sockfd, const void* msg, int len, unsigned int flags, const struct sockaddr* to, int tolen);
a、sockfd
:用于传输数据的socket描述符。
b、msg
:是一个指向要发送数据的指针。
c、len
:以字节为单位的数据的长度。
d、flags
:一般情况下置为0。
e、函数返回值:为-1表示遇到错误,并且errno中包含相应的错误码,否则返回所发送数据的总数,该数字可能小于len中所规定的大小。
f、表示目的机器的IP地址和端口号。
g、tolen
:被赋值为sizeof(struct sockaddr)
。
recvfrom
函数原型:
int recv(int sockfd, void* buf, int len, unsigned int flags, struct sockaddr* from, int fromlen);
a、sockfd
:是接收数据的socket描述符。
b、buf
:是存放接收数据的缓冲区。
c、len
:以字节为单位的缓冲区的长度。
d、flags
:一般情况下置为0。
e、函数返回值:为-1表示遇到错误,并且errno中包含相应的错误码,无错则返回读入的字节数,如果连接被中止,返回0。
f、from
:保存源机器的IP地址和端口号。
g、fromlen
:常被赋值为sizeof(struct sockaddr)
。
当对于数据报socket调用了connect()
函数时,也可以用send()
和recv()
进行数据传输,但该socket仍然是数据报socket,并利用传输层的UDP服务。但是在发送或接收数据报时,内核会自动为它加上目的地址和源地址信息。
8.close()
和shutdown()
函数
??当所有的数据操作结束后,可以调用close
函数来释放该socket资源,从而停止在该socket上的任何数据操作。
??也可以调用shutdown
函数,允许只停止在某个方向上的数据传输,而另一个方向上的数据传输继续进行。例如可以关闭某一个socket上的写操作uo允许继续在该socket上接收数据,直到读入所有数据。
??但是,shutdown
函数并不关闭套接字所占用的所有资源,除非调用close
函数来释放。
看看两个函数原型:
close(int sockfd);
shutdown(int sockfd, int how);
how参数的值和含义:
0:不允许继续接收数据;
1:不允许继续发送数据;
2:不允许继续发送和接收数据。
shutdown
在操作成功时返回0,错误时返回-1,并置errno值。
9.字节顺序转换函数
htons()
:Host to Network Short的缩写,该函数将主机的无符合短整型数字节顺序转换成网络字节顺序。
htonl()
:Host to Network Long的缩写,该函数将主机的无符合长整型数字节顺序转换成网络字节顺序。
ntohs()
:Network to Host Short的缩写,该函数将无符号短整型数从网络字节顺序转换为主机字节顺序。
ntohl()
:Network to Host long的缩写,该函数将无符号长整型数从网络字节顺序转换为主机字节顺序。
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 2000行 | 20篇 | 200小时 | |
第一周 | 83/83 | 1/1 | 8/8 | |
第六周 | 75/158 | 2/3 | 10/18 |
2018-2019-1 20165201 《信息安全系统设计基础》第8周学习总结
标签:eof 图片 参数 之间 上进 上传 博客 顺序 进度
原文地址:https://www.cnblogs.com/cbmwtsl/p/10017448.html