什么是socket?
Socket即为套接字,是计算机之间进行网络通信的一种方式,基于计算机网络中的TCP(UDP)/IP层。
在linux中,socket被视为一个文件,即在完成一系列操作后,可以用类似读写文件的方式对socket进行操作,实现与网络通信。
TCP/UDP对比
1.TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
2.TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
3. TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的
UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)
4.每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
5. TCP首部开销20字节;UDP的首部开销小,只有8个字节
6. TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道。
端口号作用
一台拥有IP地址的主机可以提供许多服务,比如Web服务、FTP服务、SMTP服务等
这些服务完全可以通过I个IP地址来实现。那么,主机是怎样区分不同的网络服务呢?显然不能只靠IP地址,因为IP地址与网络服务的关系是—对多的关系。
实际上是通过“IP地址+端口号"来区分不同的服务的。端口提供了一种访问通道,服务器一般都是通过知名端口号来识别的。例如,对于每个TCP/IP实现来说,FTP服务器的TCP端口号都是2I,每个Telnet服务器的TCP端口号都是23,每个TFTP(简单文件传送协议)服务器的UDP端口号都是69
字节序
字节序指的是多字节数据在计算机内存中存储或网络传输时各字节的存储顺序。
常见字节序
Little endian(小端字节序):低位字节存储在内存的起始地址(低地址端),高位字节存储在内存的高地址端。
Big endian(大端字节序):高位字节存储在内存的起始地址(低地址端),低位字节存储在内存的高地址端。 网络字节序=大端字节序。
Socket服务器、客户端开发
1、socket()
int socket(int domain, int type, int protocol);//返回文件描述符
参数说明:
domain:指明所用的协议族,通常为AF_INET,表示互联网协议族(TCP/IP协议族)。
type:指定socket类型。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等)。
protocol:指定协议。通常赋值为"0"。0表示选择type类型队形的默认协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。
2、bind()
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);//返回0则表示绑定成功,非0则失败
功能:用于绑定IP地址和端口号到socketfd
参数:sockfd:是socket描述符
addr:一个指向包含有本机IP地址和端口号等信息的sockaddr类型的指针,指向要绑定给sockfd的协议地址结构,这个结构结构根据地址创建socket时的地址协议族的不同而不同。
addrlen:结构体长度。
3、listen()
如果作为一个服务器,在调用socket()、bind()之后就会调用listen()来监听这个socket,如果客户端这时调用connect()发出连接请求,服务器端就会接收到这个请求。
int listen(int sockfd, int backlog);
参数:第一个参数即为要监听的socket描述符号,第二个参数为相应socket可以排队的最大连接个数。
4、connect()
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
第一个参数即为客户端的socket描述字,第二参数为服务器的socket地址,第三个参数为socket地址的长度。客户端通过调用connect函数来建立与TCP服务器的连接。
5、accept()
TCP服务器端依次调用socket()、bind()、listen()之后,就会监听指定的socket地址了。TCP客户端依次调用socket()、connect()之后就向TCP服务器发送了一个连接请求。TCP服务器监听到这个请求之后,就会调用accept()函数取接收请求,这样连接就建立好了。之后就可以开始网络I/O操作了,即类同于普通文件的读写I/O操作.
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); //返回连接connect_fd
6、read()
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
read函数是负责从fd中读取内容.当读成功时,read返回实际所读的字节数,如果返回的值是0表示已经读到文件的结束了,小于0表示出现了错误。如果错误为EINTR说明读是由中断引起的,如果是ECONNREST表示网络连接出了问题。
7、write()
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数。失败时返回-1,并设置errno变量。 在网络程序中,当我们向套接字文件描述符写时有俩种可能。1)write的返回值大于0,表示写了部分或者是全部的数据。2)返回的值小于0,此时出现了错误。我们要根据错误类型来处理。如果错误为EINTR表示在写的时候出现了中断错误。如果为EPIPE表示网络连接出现了问题(对方已经关闭了连接)。
8、close()
#include <unistd.h>
int close(int fd);
close一个TCP socket的缺省行为时把该socket标记为以关闭,然后立即返回到调用进程。该描述字不能再由调用进程使用,也就是说不能再作为read或write的第一个参数。