1 Socket Server 源代码
服务端计划只启动一个线程,所以功能实现时使用了一些全局变量。
1 int32_t skt_s_listen_fd{-1}; 2 pthread_t thr_server; 3 struct sockaddr_un srv_addr; 4 struct sockaddr_un cli_addr; 5 std::vector<int32_t> com_fd_vec; 6 7 void *serverSocketThd(void *arg) 8 { 9 SLOG_I("Start receive - server."); 10 11 // listen sockfd 12 int32_t ret = listen(skt_s_listen_fd, 1); 13 if(ret == -1) 14 { 15 SLOG_E("cannot listen the client connect request: %d - %s", errno, strerror(errno)); 16 close(skt_s_listen_fd); 17 unlink(SOCK_PATH); 18 return NULL; 19 } 20 const char *ready_flag = "LeoTest"; 21 while(1) 22 { 23 //have connect request use accept 24 socklen_t len = sizeof(cli_addr); 25 //accept the client 26 int32_t com_fd = accept(skt_s_listen_fd, (struct sockaddr*)(&cli_addr), &len); 27 28 if(com_fd < 0) 29 { 30 SLOG_E("cannot accept client connect request: %d - %s", errno, strerror(errno)); 31 close(skt_s_listen_fd); 32 unlink(SOCK_PATH); 33 return NULL; 34 } 35 36 char buf[64] = {0}; 37 int32_t recv_size(0); 38 39 recv_size = read(com_fd, buf, 10); 40 SLOG_I("Socket readed [%d] info: %s", com_fd, buf); 41 if (0 == strncmp(buf, ready_flag, 5)) 42 { 43 com_fd_vec.push_back(com_fd); 44 } 45 } 46 47 return NULL; 48 } 49 50 void socket_server_init() 51 { 52 int32_t ret; 53 SLOG_I("Init socket start[%s].", SOCK_PATH); 54 55 skt_s_listen_fd = socket(AF_UNIX, SOCK_STREAM, 0); 56 if(skt_s_listen_fd < 0) { 57 SLOG_E("cannot create communication socket: %d - %s", errno, strerror(errno)); 58 return ; 59 } 60 61 // set server addr_param 62 srv_addr.sun_family = AF_UNIX; 63 strcpy(srv_addr.sun_path, SOCK_PATH); 64 unlink(SOCK_PATH); 65 66 // bind sockfd & addr 67 ret = bind(skt_s_listen_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr)); 68 if(ret == -1) { 69 SLOG_E("cannot bind server socket[%s]: %d - %s", SOCK_PATH, errno, strerror(errno)); 70 close(skt_s_listen_fd); 71 unlink(SOCK_PATH); 72 return ; 73 } 74 // scheduler_ = new std::thread(&serverSocketThd, nullptr); 75 if (EOK != pthread_create(&thr_server, NULL, serverSocketThd, nullptr)) { 76 SLOG_E("create connect thread failed: %d - %s", errno, strerror(errno)); 77 } 78 else { 79 } 80 81 SLOG_I("Init socket end."); 82 }
2 Socket Client 源代码
客户端计划启动多个(如:30个)线程,所以客户端实现时没有使用全局变量,尽量做到线程无关。
void socket_client_init(int *enter);int sendMsg_client_ready(int fd) {char buf_send[] = "READY";SLOG_I("send READY to svr.");return write(fd, buf_send, sizeof(buf_send)); }// recv message void *recv_client_thread(void *arg) {if (NULL == arg){SLOG_E("[recv_client_thread]param is not allow NULL.");return NULL;}SLOG_I("[recv_client_thread]receive thread starting<tid=%lu>...", pthread_self());RecvModel *model = (RecvModel *)arg;ssize_t flag = 0;unsigned char buf_recv[64] = {0};ssize_t length = 0;usleep(300);SLOG_D("create communication send data");sendMsg_client_ready(model->st);SLOG_D("create communication send data end");while(true){flag = recv(model->st, buf_recv, sizeof(buf_recv), 0);if (0 == flag){ // 需要考虑重连机制SLOG_E("[recv_client_thread]remote already close connect.");break;}else if (-1 == flag){ // 需要考虑重连机制SLOG_E("[recv_client_thread]recv failed. error message : %s", strerror(errno));break;}length = flag;SLOG_D("receive data(length: %d): %s", length, buf_recv);memset(buf_recv, 0, sizeof(buf_recv));}close(model->st);return NULL; }void *client_connect_thread(void *arg) {SLOG_I("[client_connect_thread]enter: 0x%x", arg);if(NULL != arg) {int *enter = (int *)arg;SLOG_I("[client_connect_thread]enter[%d]...", *enter);int connect_fd;int ret;int count_connect = 0;static struct sockaddr_un srv_addr;// char sock_path_str[128] = {0}; SLOG_I("create communication socket...");// create unix socketconnect_fd = socket(PF_UNIX, SOCK_STREAM, 0);if(connect_fd < 0) {SLOG_E("cannot create communication socket");return NULL;}SLOG_D("create communication socket end");srv_addr.sun_family = AF_UNIX;// sprintf(sock_path_str, SOCK_PATH, count); strcpy(srv_addr.sun_path, SOCK_PATH);// connect serverret = connect(connect_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr));SLOG_I("create communication connect end: %d", ret);while(-1 == ret) {count_connect++;SLOG_W("connect to the server failed, trying no. %d", count_connect);sleep(1);ret = connect(connect_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr));}RecvModel model;model.st = connect_fd;model.addr = &srv_addr;// 开启线程--接收线程 pthread_t thr_recv;if (pthread_create(&thr_recv, NULL, recv_client_thread, &model) != 0){SLOG_E("create recv thread failed");}else{SLOG_I("create communication pthread join");pthread_join(thr_recv, NULL);SLOG_W("create communication pthread join end");}} }void socket_client_init(int *enter) {pthread_t thr_connect;SLOG_I("* * * * * * * * * * * * * * * * * * [socket_client_init]starting[%d]...", *enter);{if (EOK != pthread_create(&thr_connect, NULL, client_connect_thread, (void *)enter)){SLOG_E("create connect thread failed");}else{// pthread_join(thr_connect, NULL); // PTHREAD_CREATE_JOINABLE 属性(默认值)需要调用此函数 - 此函数会阻塞直到线程退出 }} }
3 调用示例代码
因为测试代码是写在同一个应用中,所以使用命令行参数进行区分【将命令行参数转化为控制变量: isSktFlag】
if(2 == isSktFlag) {// socket client: connect to serverfor(int i = 0; i < 30; i++) {SLOG_D("[socket] client start %d...", i);socket_client_init(&i);std::this_thread::sleep_for(std::chrono::milliseconds(100));}std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 1000)); // 因为后面还有其它测试代码, 所以增加此行延时 }else if(1 == isSktFlag) {SLOG_D("[socket] server start...");socket_server_init();std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 1000)); // 因为后面还有其它测试代码, 所以增加此行延时 }
只运行 Server 时查看 uds 信息如下:
再运行 client 后查看 uds 信息如下: