- 1. 服务端客户端编程模式
- 2. TCP的服务端程序实现步骤
- 3. 实例
- 服务端长期暴露于网络,被动等待客户端的连接
- 客户端则发起连接动作,等待服务端做出相应
- 特点:
- 服务端无法自己主动连接客户端
- 客户端只能按照预定义的方式连接客户端
-
创建套接字
-
bind函数向套接字分配地址以及端口
函数说明:
#include
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 返回值:成功 0,否则 -1
参数说明:
- sockfd 待分配ip和端口的套接字文件描述符
- addr 地址端口信息的结构体
- addrlen 地址结构体变量长度
-
等待请求连接
调用listen函数后,套接字进入等待连接请求。只有调用了listen函数,客户端才能进入可发出连接请求状态,即这时客户端才能调用connect函数(若提前调用将发生错误问题)。
函数原型:
#include
#include int listen(int sockfd, int backlog); 返回值:成功0,失败-1
参数说明:
- sockfd:用于监听的套接字
- backlog:连接请求等待队列的长度,如,该值5,表示最多使5个连接请求进入等待连接的队列
先解释一下等待连接请求状态的含义和连接请求等待队列含义,服务端处于等待连接请求状态是指,客户端请求连接时受理连接前一直处于请求等待状态
由图可知listen函数第一个参数的作用:可以理解成服务器端用于接收连接请求的一个门卫,当客户端有新连接请求时,服务端套接字就会将客户端的连接请求数据"请到"连接请求等候室,listen函数第二个参数就是这个等候室的大小,等候室被称为连接请求队列。该参数的大小与服务器的性能有联系。
-
处理/受理客户端连接请求
调用listen函数后,如果有新的连接请求,则应按序受理。受理请求即进入可接受数据状态。数据通讯要使用套接字来完成,服务端已经有一个“门卫”套接字,但是这个套接字不能用于数据交换,不然谁来守门?所以服务器端要创建一个新的套接字与客户端套接字进行数据交换。
accept函数用于创建与客户端套接字连接的套接字。
函数原型:
#include
#include int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); 返回值:成功:文件描述符,失败:-1
参数说明:
- sockfd: 服务端套接字文件描述符
- addr:用于保存发起连接请求的客户端地址信息,调用accept函数后,该值会被自动进行填充
- addrlen:第二个结构体的长度
accept函数调用成功后,内部将会自动创建一个用于和客户端套接字连接的套接字,并返回其文件描述符,并自动与发起连接的客户端建立对应的连接。
-
完成数据交换
-
断开套接字
实验目的:测试socket数据交换,listen 8899端口,使用网络调试工具模拟client,与服务端程序进行数据读写,client发送数据到服务端,当服务端接收的数据量大于16字节时,服务端向客户端发送"Hello world!".
#include#include #include #include #include #include #include int main(int argc ,char* argv[]) { int server = 0; struct sockaddr_in saddr = {0}; int client = 0; struct sockaddr_in caddr = {0}; socklen_t asize = 0; int len = 0; char buf[32] = {0}; int r = 0; server = socket(PF_INET, SOCK_STREAM, 0); if( server == -1 ) { printf("server socket errorn"); return -1; } saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); saddr.sin_port = htons(8899); if( bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1 ) { printf("server bind errorn"); return -1; } if( listen(server, 1) == -1 ) { printf("server listen errorn"); return -1; } printf("server start successn"); asize = sizeof(caddr); client = accept(server, (struct sockaddr*)&caddr, &asize); if( client == -1 ) { printf("client accept errorn"); return -1; } printf("client: %dn", client); len = 0; do { int i = 0; r = recv(client, buf, sizeof(buf), 0); if( r > 0 ) { len += r; } printf("recv %s", buf); } while ( len <16 ); printf("n"); send(client, "Hello world!", 12, 0); sleep(1); close(client); close(server); return 0; }



