服务器与客户端
P94-P98先学习基础
再学习socket编程
参考https://www.freecplus.net/
1、网络编程基础
1.1 socket通信概念
socket,也叫套接字,描述了计算机是IP地址和端口,计算机程序之间采用socket进行通信。socket把复杂的TCP/IP协议族隐藏在接口后面,方便使用。
1.2 socket套接字
tcp提供流和数据报两种通信方式,所以套接字也分为流套接字和数据报套接字
流套接字:有序、可靠、双向的,类型是SOCK_STREAM,有错误重传机制(现在用的更多,主要学习)
数据报套接字:不需要建立或者维持连接,采用UDP/IP协议,速度快,不可靠
1.3 socket通信过程
1.4 C/S服务模式
1.5 注意事项
1.5.1 服务端程序绑定地址
1)指定ip
服务器可能有多个网卡
m_servaddr.sin_addr.s_addr = inet_addr("192.168.149.129"); // 指定ip地址
2)任意ip
m_servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 本主机的任意ip地址
1.5.2 服务端程序绑定端口
m_servaddr.sin_port = htons(5000); // 通信端口
1.5.3 客户端程序指定服务端的ip地址
struct hostent* h;
if ( (h = gethostbyname("118.89.50.198")) == 0 ) // 指定服务端的ip地址。
{ printf("gethostbyname failed.\n"); close(sockfd); return -1; }
1.5.4 客户端程序指定服务端的通信端口
servaddr.sin_port = htons(5000);
1.5.5 send函数
注意即使socket被断开,send函数也不会立即报错。
1.5.6 recv函数
1.5.7 服务端有两个socket
一个是用于监听客户端的socket,还有一个是客户端连接成功后由accept创建的用于与客户端收发报文的的socket
1.5.8 程序退出时要先关闭socket
socket是系统资源,操作系统打开的socket数量是有限的,在程序退出之前必须关闭已打开的socket,就像关闭文件指针一样,就像delete已分配的内存一样,极其重要。
值得注意的是,关闭socket的代码不能只在main函数的最后,那是程序运行的理想状态,还应该在main函数的每个return之前关闭。
1.6 库函数
1.6.1 socket函数
函数声明:
int socket(int domain, int type, int protocol);
domain:协议族,一般填AF_INET
type:socket类型,一般填SOCK_STREAM
protocol:指定协议,一般为0
1.6.2 gethostbyname函数
函数声明:
struct hostent *gethostbyname(const char *name);
name:域名或ip地址
返回hostent结构体指针,用于客户端
1.6.3 connect函数
int connect(int sockfd, struct sockaddr * serv_addr, int addrlen);
功能:将sockfd对应的socket连接至serv_addr指定的服务端
sockfd:已经建立好的socket对应的id
serv_addr:指定服务端的结构体
addrlen:serv_addr结构体对应的长度
成功返回0,失败返回-1
1.6.4 bind函数
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
功能:服务端用于把通信的地址和端口绑定到socket上
sockfd:socket对应的id
addr:存放了服务端用于通信的地址和端口
addrlen:addr结构体的长度
可能出错的原因:地址无效,或者端口被占用
1.6.5 listen函数
函数声明:
int listen(int sockfd, int backlog);
sockfd:是已经被绑定的socket对应的id
listen函数把主动连接套接字变为被动连接的套接字,使得这个socket可以接受其它socket的连接请求,从而成为一个服务端的socket。
1.6.6 accept函数
int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);
功能:accept函数等待客户端的连接,如果没有客户端连上来,它就一直等待,这种方式称之为阻塞,连接成功后创建新的套接字,服务端程序用这个新的套接字和客户端进行报文的收发
1.6.7 函数调用总结
服务端:socket->bind->listen->accept->recv/send->close
客户端:socket->connect->send/recv->close