Linux回调函数客户端简单示例

Linux回调函数客户端简单示例

​ 回调函数就是一个被作为参数传递的函数。在C语言中,回调函数只能使用函数指针实现,在C++、Python、ECMAScript等更现代的编程语言中还可以使用仿函数或匿名函数。

​ 回调函数的使用可以大大提升编程的效率,这使得它在现代编程中被非常多地使用。同时,有一些需求必须要使用回调函数来实现。使用回调函数就会让别的程序员调用我们的代码时操作简单。

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 *)&param);
    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

编译:gcc *c -o test -lpthread

执行:./test ip地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值