基于TCP(面向链接)的socket编程
Server端的流程如下:
-
1 创建Socket套接字
-
2 将套接字绑定到一个本地地址(IP)和端口(port)上
-
3 将套接字设置为监听模式,准备接收客户端请求(listen)
-
4 等待客户端请求,当请求到来后,接受链接请求,返回一个新的对应于此次链接的套接字(accept)
-
5 用返回的套接字和客户端进行通信(send/recv read/write)
-
6 返回,等待另一个客户请求
-
7 关闭套接字
/*
*tcp_server.c
*/
#include "tcp-server.h"
#include <arpa/inet.h>
#include <errno.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
static const size_t MAX_FRAME_SIZE = 4100;
static const int PORT = 1234;
static device_t tcp_device;
static int listen_fd = -1;
static int tcp_server_init(device_t *dev) {
struct sockaddr_in addr;
//创建socket,获取一个socket描述符
if ((listen_fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
fprintf(stderr, "%s(): cannot create socket", __FUNCTION__);
return -1;
}
//设置server的地址同通信协议
memset(&addr, 0, sizeof(struct sockaddr_in));
//协议族: AF_INET AF_INET6 AF_LOCAL
addr.sin_family = AF_INET;
//取本地任意一个地址进行通信
// uint32_t htonl(uint32_t hostlong) 将主机无符号长整型转化为网络字节
//INADDR_ANY=0.0.0.0
addr.sin_addr.s_addr = htonl(INADDR_ANY);
// uint16_t htons(uint16_t hostshort) 将hostshort 转化为网络字节序
//网络字节采用大端模式(big-ending),高位存放在低地址
addr.sin_port = htons(PORT);
if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) != 0) {
fprintf(stderr, "%s(): bind() failed", __FUNCTION__);
goto failed;
}
if (listen(listen_fd, LISTEN_BACKLOG) != 0) {
fprintf(stderr, "%s(): listen() failed", __FUNCTION__);
goto failed;
}
fprintf(stderr, "%s(): tcp_server running on %s port=%d\n", __FUNCTION__, inet_ntoa(addr.sin_addr), PORT);
dev->recv_buf = (