赞
踩
绝大多数 TCP 服务器端都按照如下顺序调用:
在 Windows 环境下,代码表示为:
WSADATA wsaData; SOCKET hServSock, hClntSock; SOCKADDR_IN servAddr, clntAddr; int szClntAddr; /*Windows 环境 Socket 编程必须*/ if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0) //错误处理 /*创建套接字,使用 IPv4 协议族、面向连接的 TCP 数据传输方式,对于 IPv4 协议族,第三个参数总是为 0 */ hServSock = socket(PF_INET, SOCK_STREAM, 0); if(hServSock == INVALID_SOCKET) //错误处理 /*设置协议族的地址信息*/ memset(&servAddr, 0, sizeof(servAddr)); servAddr.sin_family = AF_INET; //地址族设置为 IPv4 servAddr.sin_addr.s_addr = htonl(INADDR_ANY); //设置 IP 地址 servAddr.sin_port = htons(atoi(argv[1])); //设置端口号 /*分配套接字地址*/ if(bind(hServSock, (SOCKADDR *)&servAddr, sizeof(servAddr)) == SOCKET_ERROR) //错误处理 /*等待连接请求*/ if(listen(hServSock, 5) == SOCKET_ERROR) //错误处理 /*受理客户端连接请求*/ szClntAddr = sizeof(clntAddr); hClntSock = accept(hServSock, (SOCKADDR *)&clntAddr, &szClntAddr); if(hClntSock == INVALID_SOCKET) //错误处理 /*接收数据*/ strLen = recv(hClntSock, message, BUF_SIZE,0); /*发送数据*/ send(hClntSock, (const char *)&calculation_result, sizeof(int), 0); closesocket(hClntSock); closesocket(hServSock); WSACleanup();
绝大多数 TCP 客户端都按照如下顺序调用:
在 Windows 环境下,代码表示为:
WSADATA wsaData; SOCKET hClntSock; SOCKADDR_IN servAddr; /*Windows 环境 Socket 编程必须*/ if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0) //错误处理 /*创建套接字,使用 IPv4 协议族、面向连接的 TCP 数据传输方式,对于 IPv4 协议族,第三个参数总是为 0 */ hClntSock = socket(PF_INET, SOCK_STREAM, 0); if(hClntSock == INVALID_SOCKET) //错误处理 /*设置协议族的地址信息*/ memset(&servAddr, 0, sizeof(servAddr)); servAddr.sin_family = AF_INET; servAddr.sin_addr.s_addr = inet_addr(argv[1]); servAddr.sin_port = htons(atoi(argv[2])); /*连接到服务器*/ if(connect(hClntSock, (SOCKADDR *)&servAddr, sizeof(servAddr)) == SOCKET_ERROR) //错误处理 /*发送数据*/ send(hClntSock, message, strLen, 0); /*接收数据*/ recv(hClntSock, &result, sizeof(int), 0); closesocket(hClntSock); WSACleanup();
基于 TCP 的服务器端-客户端函数调用关系
客户端只能等到服务器端调用 listen
函数后才能调用 connect
函数。
TCP 套接字的数据收发无边界。服务器端即使调用 1 次 send
函数传输 40 字节的数据,客户端有可能通过 4 次 recv
函数调用每次读取 10 字节。也就是说,客户端可以缓慢的分批接收。
TCP 套接字的 I/O 是有缓冲的。send
函数调用后,数据将移至输出缓冲区;在适当的时候(不管是分别传送还是一次性传送)传向对方的输入缓冲区。 recv
函数调用后,从输入缓冲区读取数据。
socket
函数)自动生成。TCP 中的断开连接过程比建立连接过程更重要,因为连接过程中一般不会出现大的变数,但断开过程有可能发生预想不到的情况。
使用 close
或者 closesocket
函数意味着完全断开连接。完全断开连接不仅指无法传输数据,而且也不能接收数据。
还有一种断开连接的方法是只断开一部分连接,成为半关闭。半关闭是指可以传输数据但无法接收,或者可以接收数据但无法传输。
每一个套接字建立后,都会存在 2 个流:
建立套接字的两台主机,都会拥有单独的输入流和输出流。使用 close
或者 closesocket
函数将同时断开这 2 个流,而半关闭只关闭其中 1 个流。
shutdown
函数:关闭其中 1 个流// 成功返回 0,失败返回 -1
int shutdown(SOCKET s,int how);
s:套接字
how:断开方式
- SD_RECEIVE:断开输入流,套接字无法接收数据
- SD_SEND:断开输出流,套接字无法传输数据
- SD_BOTH:同时断开 I/O 流
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。