// open/close/state socket device e_int32 Socket_Open(socket_t **socket_ptr, const char *socket_addr, const e_uint32 port, e_int32 type) { int sockfd; int snd_size = 0; /* 发送缓冲区大小 */ socklen_t optlen; /* 选项值长度 */ socket_t *skt = (socket_t *) malloc(sizeof(socket_t)); e_assert(skt, E_ERROR_BAD_ALLOCATE); memset(skt, 0, sizeof(socket_t)); //保证经过网络初始化 Socket_Init(); /*创建服务器端套接字--IPv4协议*/ switch (type) { case E_SOCKET_TCP: /*面向连接通信,TCP协议*/ sockfd = socket(PF_INET, SOCK_STREAM, 0); break; case E_SOCKET_UDP: /*无连接,UDP协议*/ sockfd = socket(PF_INET, SOCK_DGRAM, 0); break; case E_SOCKET_NAME: sockfd = socket(AF_UNIX, SOCK_STREAM, 0); break; } /*check sockfd*/ if (e_failed(sockfd)) { free(skt); return E_ERROR_IO; } /* * 先读取缓冲区设置的情况 * 获得原始发送缓冲区大小 */ optlen = sizeof(snd_size); if (getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &snd_size, &optlen) < 0) { DMSG((STDOUT,"获取发送缓冲区大小错误\n")); skt->send_max_size = ~0; } else { // DMSG((STDOUT,"获取发送缓冲区大小:%d\n",snd_size)); skt->send_max_size = snd_size; } //默认是非阻塞通讯 fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK); /*存储附加信息*/ skt->priv = (void *) sockfd; if (socket_addr != NULL) hd_strncpy(skt->ip_address, socket_addr, sizeof(skt->ip_address)); skt->port = port; skt->type = type; skt->state = E_OK; skt->last_error = E_OK; (*socket_ptr) = skt; return E_OK; }
/** *\brief 创建网络会话进程。 *\param fs 定义了会话进程描述符。 *\param name 定义了进程标识符。 *\param session_id 定义了进程描述符的ID。 *\param connect 定义了海达连接属性。 *\retval E_OK 表示成功。 */ e_int32 fsocket_open(fsocket_t *fs, e_uint8 *name, e_uint32 session_id, hd_connect_t *connect) { e_int32 ret; e_assert(fs&&connect, E_ERROR_INVALID_HANDLER); memset(fs, 0, sizeof(fsocket_t)); fs->connect = connect; fs->id = session_id; ret = semaphore_init(&fs->send_sem, 1); //发送线路只有一条 e_assert(ret, E_ERROR_INVALID_CALL); ret = semaphore_init(&fs->recv_sem, 0); //消息缓存里现在有0条数据,这里缓存大小为1 e_assert(ret, E_ERROR_INVALID_CALL); if (name) hd_strncpy(fs->name, name, sizeof(fs->name)); fs->state = 1; return E_OK; }
/* inet_aton() returns non-zero if the address is a valid one, and it returns zero if the address is invalid. inet_ntoa() returns the dots-and-numbers string in a static buffer that is overwritten with each call to the function. inet_addr() returns the address as an in_addr_t, or -1 if there's an error. (That is the same result as if you tried to convert the string "255.255.255.255", which is a valid IP address. This is why inet_aton() is better.) #include<sys/socket.h> int accept(int sockfd, struct sockaddr* addr, socklen_t* len) 返回:非负描述字——成功, -1——失败 对于服务器编程中最重要的一步等待并接受客户的连接,那么这一步在编程中如何完成,accept函数就是完成这一步的。 它从内核中取出已经建立的客户连接,然后把这个已经建立的连接返回给用户程序,此时用户程序就可以与自己的客户进行点到点的通信了。 */ e_int32 Socket_Accept(socket_t *socket, socket_t **socket_c) { int sockfd; int ret; socklen_t addr_len; char *ip_address; socket_t *skt; /*接收返回的客户端信息*/ struct sockaddr_in peer_address; e_assert((socket && socket->state), E_ERROR); sockfd = (int) socket->priv; //接受连接 ret = accept(sockfd, (struct sockaddr *) &peer_address, &addr_len); if (ret < 0) { if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) return E_ERROR_RETRY; else return E_ERROR_INVALID_CALL; } /*创建客户会话*/ skt = (socket_t *) malloc(sizeof(socket_t)); e_assert(skt, E_ERROR_BAD_ALLOCATE); memset(skt, 0, sizeof(socket_t)); /*存储附加信息*/ skt->priv = (void *) ret; ip_address = inet_ntoa(peer_address.sin_addr); // resolve IP in antelope e_assert(ip_address, E_ERROR_INVALID_ADDRESS); hd_strncpy(skt->ip_address, ip_address, sizeof(skt->ip_address)); skt->port = ntohs(peer_address.sin_port); skt->type = socket->type; skt->send_max_size = socket->send_max_size; skt->state = E_OK; skt->last_error = E_OK; (*socket_c) = skt; return E_OK; }