细谈电商网站外链建设的策略,wordpress菜单 自定义大小写,如皋市城乡建设局网站,有啥创意可以做商务网站的1.TCP通信程序的编写 面向连接、可靠传输、提供字节流传输服务 客户端向服务器发送一个连接建立的请求流程#xff0c;上图中服务端第三步详细流程 2.TCP接口 socket--创建套接字 int socket(int domain, int type, int protocol); bind---绑定 intbind(int sockfd, struct s… 1.TCP通信程序的编写 面向连接、可靠传输、提供字节流传输服务 客户端向服务器发送一个连接建立的请求流程上图中服务端第三步详细流程 2.TCP接口 socket--创建套接字 int socket(int domain, int type, int protocol); bind---绑定 intbind(int sockfd, struct sockaddr*addr, socklen_len); sockfd : socket返回的套接字描述符 addr: 要绑定的地址信息不同地址域类型有不同的地址结构 listen--监听 int listen(int sockfd, int backlog); 注意listen第二个参数限制的是同一时刻最大并发连接数而不是总体能建立的连接数量因为随着accept取出一个已完成连接就又可以建立一个新的连接放在队列中。 connect--向服务端发送连接请求这个接口只有客户端用到 int connect(int sockfd, struct sockaddr *adddr, socklen_t len); sockfd:套接字描述符 addr: 服务端的地址信息 addrlen:地址长度 accept--获取新建连接 int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) 从内核sockfd指定的监听套接字对应的已完成连接队列中取出一个socket并返回这个socket的描述符 通过addr参数返回具体连接请求来源于哪个客户端 addr: accept内部进行填充客户端地址是一个输出参数 addrlen: 地址信息长度输入输出参数用于指定想要获取的地址长度以及返回实际的地址长度 返回值: 成功则返回新建连接的套接字描述符; 出错返回-1 send/recv--收发数据 ssize_t send(int sockfd, void *data, size_t len, int flag); 相较于sendto不用在指定对端地址了返回值: 成功则返回实际发送的数据长度; 出错则返回-1 ssize_t recv(int sockfd, void *buf, size_t len, int flag) 相较于recvfrom不用获取对端地址了返回值: 成功则返回实际发送的字节长度; 出错则返回-1; 连接断开则返回0 tcp是面向连接的一旦连接断开 (对方可能关闭了连接或者网络出问题了......)将无法继续通信 recv函数返回0没有读到数据是一回事最主要的是要告诉使用者连接断开了 close--关闭套接字 int close(int fd); 3.封装一个TCPSocket类 主要是对socket操作进行封装简化使用难度,下面为主要过程具体代码见xshell 问题的探讨: tcp服务器涉及到对多个socket进行操作 (有多少客户端连接上来就有多少socket)每一个socket都需要 accept recv send,但是这三个操作都是阻塞操作 accept如果没有新连接到来就会阻塞 recv如果客户端没有发送数据就会阻塞 因此一旦获取了一个新连接但是这个新连接一直不发送数据就会卡在recv处没办法去调用accept获取下一个连接了而一旦一个连接通信完毕程序流程运行到accept但是这时没有新连接就会卡在这里就算上一个连接发送数据也无法处理 tcp服务器觉得别扭的本质原因: 在一个执行流中进行的操作太多并且这些操作都是阻塞操作。 解决方案:既然一个执行流中不能进行多个阻塞操作干脆就创建多个执行流(多执行流任务处理) 主执行流只干一件事: 针对监听套接字获取新建连接获取了一个新连接就为这个新连接的操作创建一个执行流 其他执行流干的事情: 每个执行流都只负责与一个客户端通信 这样做有个好处任意一个线程阻塞都不会影响其他线程也就是不会影响与其他客户端的通信 具体的实现过程分为两种: 多进程多线程 多进程: 稳定健壮 多线程:灵活消耗小。 多进程方案实现 多进程方案实现: accept之后创建子进程;但是需要注意僵尸进程的处理 相较于多进程版本流程上没有大的差别也是获取一个新建连接之后创建一个线程出来 注意事项: 线程间是共用同一个文件描述符表因此对这个通信套接字描述符的操作只能由负责这个描述符操作的线程进行关闭其他的线程不能关闭。 局部变量的使用线程创建的时候千万要注意传参不能因为传递局部变量地址而导致线程内访问的时候出现内存访问错误 4.tcp通信程序编写与运行中遇到的一些特殊情况 连接断开: tcp是面向连接的通信一旦连接断开就无法通信 问题:如何在代码中知道连接断开了? 连接断开后在代码中的体现是什么? 当recv函数接收数据的时候返回0代表的不仅仅是没有接收到数据更多是为了表示连接断开了!!! 当send函数发送数据的时候程序直接异常 (SIGPIPE) 退出 因此如果网络通信中不想让程序因为连接断开而导致发送数据的时候程序异常退出就对SIGPIPE信号进行处理 问题: 有时候网络程序关闭后无法立即启动会bind绑定地址报错绑定失败地址已经被使用 网络通信程序如果程序是主动关闭的一方程序会无法立即启动 因为一个程序主动关闭了连接这个连接并不会立即被释放(对应的地址和端口依然被占用)而是要等待一段时间。 netstat-anptu命令 这是查看主机上所有网络连接状态的命令