在学习之余,因为一个小项目,需要用到网络编程TCP/IP的方式来连接到服务器端的数据库中。所以便在网上看了一些教材和帖子,学习了一下,但是还是有一些问题在此讨论讨论。
Socket是个什么东西大家就都知道了,我就不去复制粘贴啦。那咱首先介绍什么呢?咱来介绍一下socket编程的头文件
sys/types.h:数据类型定义
sys/socket.h:提供socket函数及数据结构
netinet/in.h:定义数据结构sockaddr_in
arpa/inet.h:提供IP地址转换函数
netdb.h:提供设置及获取域名的函数
sys/ioctl.h:提供对I/O控制的函数
sys/poll.h:提供socket等待测试机制的函数
但是有个问题出现了,我在Windows的编译环境下复制了上述头文件却报错了:C:\Users\14246\Desktop\server-sql.c [Error] sys/socket.h: No such file or directory。
这是为什么呢?因为这是在Linux下编译的时候的头文件,也就是说我的服务器是centos7的操作系统,那么可以用上述的头文件。但是我现在是在Windows下写的客户端,所以找不到该头文件的路径。
那该咋办呢?把上述头文件换成:#include
头文件讲完了,那讲一讲socket编程常用的一些API函数:
①socket()函数:此函数用于创建一个Socket的描述符,这个描述符说明了此次使用的协议。后面的其他函数会调用这个描述符来作为参数;
int socket(int domain, int type, int protocol)
第一个参数是协议域 :常用的协议族有,AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。
第二个参数是socket类型:常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等
第三个参数是指定的协议:常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议
注意:并不是上面的type和protocol可以随意组合的,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当protocol为0时,会自动选择type类型对应的默认协议。
②bind()函数 把一个地址族中的特定地址进行数据的收发。通常服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个。
int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
第一个参数是socket描述符:它是通过socket()函数创建了,唯一标识一个socket。bind()函数就是将给这个描述字绑定一个名字
第二个参数是指向要绑定给Sockfd的协议地址
第三个参数是对应地址的长度
③listen(),connect()函数
若是服务器,在调用前两个函数之后,便会调用listen()函数来监听bind给socket的那个端口。
若是客户端,这时便调用connect()函数来发出连接请求,服务器便会收到此请求。参数便不一一解释了。
④accept()函数:
TCP服务器端依次调用了socket(),bind(),listen()函数后,就会监听指定的Socket地址了。
而客户端依次调用了socket(),connect()之后,就会向指定的TCP服务器发送了一个连接请求。而服务器接收到此请求后,就会调用accept()函数接收请求。这样就建立了连接
int accept(int sockfd, struct sockaddr* addr,socklen_t *addrlen)
注意:accept的第一个参数为服务器的socket描述字,是服务器开始调用socket()函数生成的,称为监听socket描述字;而accept函数返回的是已连接的socket描述字。一个服务器通常通常仅仅只创建一个监听socket描述字,它在该服务器的生命周期内一直存在。内核为每个由服务器进程接受的客户连接创建了一个已连接socket描述字,当服务器完成了对某个客户的服务,相应的已连接socket描述字就被关闭。
⑤read()/write()当客户端与服务器已经建立了连接后,便可以调用网络IO进行读写操作了,即实现了网络中不同进程之间的通信。
这两个函数还有一些其他函数可以替代,便不一一说明了。
⑥close()函数 在读写操作完成后,就要关闭相应的socket描述字。
#include
int close(int fd)
下面的链接是一个大佬写的详细说明:
https://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html