《回调函数 —— 线程注册回调函数》
client.h
#ifndef _HY_TCP_H #define _HY_TCP_H typedef void (* recv_callback)(char *data, int len);//定义回调 typedef struct param{ recv_callback callback; } callback_param; int tcp_dns_change(char *dns, char *str, int size); int tcp_connect(char *IP,int PORT); void tcp_disconnect(void); int tcp_send(char *buf); int tcp_recv(char *buf, int size); void *thread_recv(void *param); void tcp_register_callback(recv_callback cb); //调用回调函数 #endif
client.c
#include <stdio.h> #include <unistd.h> #include <sys/socket.h> #include <stdlib.h> #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> #include <netdb.h> #include <syslog.h> #include <pthread.h> #include <poll.h> #include "hy_tcp.h" int sockfd; enum { STATE_NOCONNECTED, //未连接 STATE_CONNECTED, //已连接 STATE_DISCONNECTE //连接断开 }; int connect_state = STATE_NOCONNECTED; int tcp_dns_change(char *dns, char *str, int size) { struct hostent *hptr; hptr = gethostbyname(dns); if (hptr == NULL) { syslog(LOG_ERR, "gethostbyname error"); return -1; } syslog(LOG_INFO, "ipaddr:%s\n", inet_ntop(hptr->h_addrtype, hptr->h_addr, str, size)); return 0; } int tcp_connect(char *IP,int PORT) { if (connect_state == STATE_NOCONNECTED) { struct sockaddr_in server_addr; sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { syslog(LOG_ERR, "create socket failed!\n"); return -1; } memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(PORT); server_addr.sin_addr.s_addr = inet_addr(IP); if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { syslog(LOG_ERR, "connet error!\n"); return -1; } connect_state = STATE_CONNECTED; syslog(LOG_INFO, "connect success!\n"); return 0; } else return -1; } void tcp_disconnect(void) { if (connect_state != STATE_NOCONNECTED) { close(sockfd); syslog(LOG_INFO, "connect is break!\n"); } } int tcp_send(char *buf) { if (connect_state == STATE_CONNECTED) { return send(sockfd, buf, strlen(buf)+1, 0); } else return -1; } void *thread_recv(void *param) { int ret; static char buf[2048] = {0}; char heartbeat_buf[] = "heartbeat data"; callback_param *p = (callback_param *)param; struct pollfd c_poll; c_poll.fd = sockfd; c_poll.events = POLLIN; memset(buf, 0, sizeof(buf)); while (1) { if (connect_state == STATE_CONNECTED) { ret = poll(&c_poll, 1, 5000); if (ret < 0) { syslog(LOG_ERR, "poll error!\n"); break; } else if (0 == ret) { if (send(sockfd, heartbeat_buf, sizeof(heartbeat_buf), 0) < 0) { connect_state = STATE_DISCONNECTE; syslog(LOG_ERR, "disconnect!\n"); break; } } else { if (recv(sockfd, buf, sizeof(buf), 0) > 0) { syslog(LOG_INFO, "recv:%s\n", buf); p->callback(buf, sizeof(buf)); } } } else break; } } void tcp_register_callback(recv_callback cb) { pthread_t recv_t; static callback_param param; param.callback = cb; pthread_create(&recv_t, NULL, thread_recv, (void *)¶m); pthread_detach(recv_t); }
main.c
#include <stdio.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <string.h> #include <arpa/inet.h> #include "hy_tcp.h" #include "hy_udp.h" #define PORT 6000 //服务器端口号 #if 1 void r_callback(char *msg, int len) { } int main(int argc, char *argv[]) { char recv_buf[1024] = {0}; char send_buf[1024] = {0}; char str[16]; recv_callback func = r_callback; if(argc < 2){ printf("required parameter missing\n"); return -1; } //tcp_dns_change(argv[1], str, sizeof(str)); tcp_connect(argv[1],PORT); tcp_register_callback(func); while(1){ memset(send_buf,0,sizeof(send_buf)); printf("please input something\n"); scanf("%s",send_buf); tcp_send(send_buf); } tcp_disconnect(); return 0; } #endif
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?