嵌入式Linux网络编程 之 简单的TCP网络编程

2019-07-12 14:25发布

 关于TCP:TCP提供的是一种面向连接的、可靠的字节流服务。                                                                        TCP网络通信流程图

补充的API 函数名称:listen() 原型:int listen(int sockfd, int backlog) 功能 : 宣告服务器能够接收的连接请求数 头文件: 成功:0 失败:-1 参数说明: sockfd : 套接字 backlog:请求队列允许的最大请求数,大多数系统默认为20
函数名称:accept() 原型:int accept(sockfd, struct sockaddr *restrict addr, socklen_t *restrict len) 功能 : 阻塞服务器,获得连接请求并建立连接 头文件: 成功:返回新的关于该连接的套接字 失败:-1 参数说明: sockfd : 套接字 addr:客户端地址信息 len:客户端地址长度
函数名称:send() 原型:int send(int sockfd, const void *buf , size_t n, int flags) 功能 : 发送数据(此时套接字必须已连接) 头文件: 成功:返回发送的字节数 失败:-1 参数说明: sockfd : 套接字 buf:待发送的数据 n:发送数据长度 flags:通常为0
函数名称:connect() --->可以看出通常是由客户端发送连接请求 原型:int connect(int sockfd, const struct sockaddr *addr, socklen_t len) 功能 : 在客户端与服务端建立连接 头文件: 成功:0 失败:-1 参数说明: sockfd : 套接字 addr:与之通信的服务器地址,如果sockfd没有绑定到一个地址,则,connect会给调用者绑定一个默认地址 len:地址长度
函数名称:recv() 原型:int recv(int sockfd, void *buf , size_t n, int flags) 功能 : 接收数据(此时套接字必须已连接) 头文件: 成功:返回接收的字节数 无可用数据则返回0 失败:返回-1 参数说明: sockfd : 套接字 buf:存放接收数据的缓冲区 n:缓冲区长度 flags:通常为0
服务器工作流程:
1. 创建、初始化服务器套接字,创建初始化服务器/客户端地址结构 2. 绑定服务器套接字(bind) 3. 监听sockfd描述符( listen ) 4. 服务器阻塞,直到获得连接请求并建立连接(accept) 5. 接收客户端发送的数据,这里以读取客户端的IP作为示例 6. 发送数据到客户端,通过新的套接字。
代码如下: #include #include #include #include #include #include #include int main(int argc, char *argv[]) { int sockfd, port, new_fd; struct sockaddr_in s_addr; struct sockaddr_in c_addr; char hello[] = "hello"; int size; /*判断用法是否正确*/ if(argc != 2) { fprintf(stderr, "usage: %s port", strerror(errno)); exit(1); } /*获取端口号*/ if((port = atoi(argv[1])) < 0) { fprintf(stderr, "Port Error: %s", strerror(errno)); exit(1); } if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { fprintf(stderr, "socket error: %s", strerror(errno)); exit(1); } /*填充sockaddr结构*/ bzero(&s_addr, sizeof(s_addr)); s_addr.sin_family = AF_INET; s_addr.sin_port = htons(port); s_addr.sin_addr.s_addr = htonl(INADDR_ANY); /*绑定套接字与描述符*/ if(bind(sockfd, (struct sockaddr*)&s_addr, sizeof(s_addr)) == -1) { fprintf(stderr, "bind error: %s", strerror(errno)); exit(1); } printf("socket... "); /*监听sockfd描述符*/ if(listen(sockfd, 10) == -1) { fprintf(stderr, "listen error: %s", strerror(errno)); exit(1); } printf(" listen... "); while(1) { size = sizeof(struct sockaddr); /*阻塞服务器,获取连接*/ printf(" accept... "); if((new_fd = accept(sockfd, (struct sockaddr*)&c_addr, &size)) < 0) { fprintf(stderr, "accept error: %s", strerror(errno)); exit(1); } fprintf(stderr, "new_fd = %d ", new_fd); /*向连接的新套接字字符发送数据*/ if((send(new_fd, hello, strlen(hello), 0)) < 0) { fprintf(stderr, "send error: %s", strerror(errno)); exit(1); } } close(sockfd); exit(0); }

客户端工作流程: 1. 判断使用方法,提取端口号 2. 创建套接字(面向字节流),初始化套接字 3. 在请求服务的进程套接字(客户端)和提供服务的进程套接字(服务端)建立连接 4. 接收数据,打印
通信演示: 服务端:
客户端: