C语言编写smtp用户代理之socket操作

来源:互联网 发布:文娱小说推荐知乎 编辑:程序博客网 时间:2024/06/05 16:45

一、函数的准备和功能介绍
首先是 renyj_sock.h文件

#ifndef RENYJ_SOCK_H#define RENYJ_SOCK_H    #include<stdio.h>#include<string.h>#include<stdlib.h>#include<unistd.h>#include<sys/types.h>#include<sys/file.h>#include<sys/socket.h>#include<ctype.h>#include<netinet/in.h>#include<netdb.h>#include<sys/ioctl.h>#include<arpa/inet.h>#include<time.h>#include<signal.h>#include<errno.h>#include<sys/wait.h>#include<pwd.h>#include<grp.h>#include<fcntl.h>#include<limits.h>#ifdef HAS_SSL  #include <openssl/ssl.h>#include <openssl/rand.h>#include <openssl/err.h>#endif/*宏定义用来打印调试信息*/#define debug(format,args...) do{fprintf(stderr,"Debug>>>%s->%s()->line.%d:"format"\n",__FILE__,__FUNCTION__,__LINE__,##args);}while(0);/*这个函数用来初始化socket并且返回一个可以使用的sokect描述符,第一个参数没有用,这里是为了扩展*/int myclient_sock(int protel,char *addr,int port,int timeout);/*这个函数用来从socket读取数据,供外界调用的接口函数*/int mysock_gets(char* str,int size,int timeout);/*这个函数用来从socket发送数据,提供给外界的接口函数*/int mysock_puts(char* str);/*从socket中读取数据,不提供给外界*/int mysock_read(int sock,char *str,int size,int timeout);/*向socket 发送数据,不提供给外界*/int mysock_write(int sock,char *str,int size);/*关闭socket*/int mysock_close();/*获取socket 描述符的值,提供给外界*/int get_socket();/*设置socket 描述符的值,提供给外界*/int set_socket(int socket);/*将IP或者域名的字符串转变成IP地址的函数,只支持IPv4*/struct in_addr *str_to_addr(char *addr);//由于使用qq邮箱需要加密传输,所以在这里需要开启ssl。#ifdef HAS_SSL//封装一个读取ssl加密后数据的函数 int mysock_read_ssl(SSL *ssl,char *str,int size,int timeout);//封装一个发送ssl数据的函数int mysock_write_ssl(SSL *ssl,char *str,int size); //获取SSL标志SSL* get_ssl();//设置ssl标志int set_ssl(SSL *ssl);//初始化 sslint openssl_init(char *cipher);//将某个socket描述符对应的socket传输的数据设置为ssl加密int turn_on_ssl(int fd);int turn_ssl_status_on();int turn_ssl_status_off();#endif#endif

二、函数的实现
renyj_sock.c文件

int renyj_fd;SSL *renyj_ssl;int renyj_ssl_status;/*初始化sokcet,准备连接*/int myclient_sock(int protel,char *seraddr,int port,int timeout){    struct sockaddr_in sa;    struct in_addr* addr;    int sock_fd;    struct timeval tv;    fd_set fdset;    //获取IP地址    addr = str_to_addr(seraddr);    if (NULL == addr)    {        debug("invalid domain");        return -1;    }    memset(&sa,0x00,sizeof(sa));        //准备通信地址    sa.sin_family = AF_INET;    sa.sin_port = htons(port);    sa.sin_addr.s_addr = addr->s_addr;    //创建socket    sock_fd = socket(AF_INET,SOCK_STREAM,PF_UNSPEC);    if (-1 == sock_fd)    {        return -1;    }    //监控socket,如果连接超时,则退出。    int rc;    rc = connect(sock_fd,(struct sockaddr*)(&sa),sizeof(sa));    if (-1 == rc)    {        debug("connect error");        return -1;    }    FD_ZERO(&fdset);    FD_SET(sock_fd,&fdset);    tv.tv_sec = timeout;    tv.tv_usec = 0;    rc = select(sock_fd+1,NULL,&fdset,NULL,&tv);    if (-1 == rc)    {        debug("select error");        return -1;    }    if (0 == rc)    {        debug("connect to %s:%d timeout after %d seconds ",                seraddr,port,timeout);        return -1;    }    //返回一个socket描述符    return sock_fd;}
int mysock_gets(char *str, int size,int timeout){#ifdef HAS_SSL    mysock_read_ssl(get_ssl(),str,size,timeout);#else    mysock_read(get_socket(),str,size,timeout); #endif}
int mysock_puts(char *str){#ifdef HAS_SSL    mysock_write_ssl(get_ssl(),str,strlen(str));#else    mysock_write(get_socket(),str,strlen(str));#endif}
int mysock_read(int sock,char *str,int size,int timeout){    if (NULL == str)    {        return -1;    }    char *cur = str;    char buff[1];    int count=0;    char lastread = 0;    int tmpcount = 0;    while (10 != lastread)    {        tmpcount = recv(sock,buff,1,0);        if (-1 == tmpcount)        {            debug("recv error");            return -1;        }        lastread = buff[0];        if ((count < size)&&(10 != lastread)&&(13!=lastread) )        {            count++;            *cur = lastread;            cur++;        }    }    if (count > 0)    {        *cur = 0;    }    return count;}
int mysock_write(int sock,char *str,int count){    int curcount = 0;    int bytessent = 0;    while (bytessent < count)    {        curcount = send(sock,str,count-bytessent,0);        if (curcount < 0)        {            debug("send error");            return curcount;        }        bytessent = bytessent + curcount;        str += curcount;     }    return count;}
int mysock_close(){    close(renyj_fd);}int get_socket(){    return renyj_fd;}int set_socket(int socket){    renyj_fd = socket;}
struct in_addr *str_to_addr(char *addr){    static struct in_addr myaddr;    struct hostent *host;    myaddr.s_addr=inet_addr(addr);    if(-1!=myaddr.s_addr)    {        return (&myaddr);     }    host = gethostbyname(addr);    if (NULL == host)    {        return NULL;    }    return (struct in_addr*)(*host->h_addr_list);}
#ifdef HAS_SSL SSL *get_ssl(){    return renyj_ssl;}int set_ssl(SSL *ssl){    renyj_ssl = ssl;}int openssl_init(char *cipher){    static const char rnd_seed[]="my huge entropy for rng.. blah";    SSL_CTX *ssl_ctx=(SSL_CTX *) NULL;    SSL *ssl=NULL;    SSL_library_init();    SSL_load_error_strings();    RAND_seed(rnd_seed,sizeof(rnd_seed));    OpenSSL_add_all_algorithms();    ssl_ctx=SSL_CTX_new(SSLv23_client_method());    if (ssl_ctx == NULL)    {        debug("Could not create SSL context\n");        return -1;    }    if (cipher)    {        if (!SSL_CTX_set_cipher_list(ssl_ctx,cipher))        {            debug("Could not set cipher list %s\n",cipher);            return -1;        }    }    ssl=SSL_new(ssl_ctx);    if (ssl == NULL)    {        debug("SSL_new() failed\n");        return -1;    }    /* set ssl to msock's static */    set_ssl(ssl);}int turn_on_ssl(int fd){    int        rc=(-1);    SSL        *ssl;    ssl = get_ssl();    if (ssl)    {        if (!SSL_set_fd(ssl,fd))        {            debug("turn_on_raw_ssl: failed to set socket %d to SSL\n",fd);            return(-1);        }        /* must set back to msock's static */        set_ssl(ssl);        debug("connect ...");        rc=SSL_connect(ssl);        if (rc < 1)        {            debug("turn_on_raw_ssl: SSL connection failed\n");            return(-1);        }        debug("connect end ")        rc=0;        return(0);    }    return(-1);}int turn_ssl_status_on(){    renyj_ssl_status = 1;}int turn_ssl_status_off(){    renyj_ssl_status = 0;}int mysock_write_ssl(SSL *ssl,char *str,int count){    int curcount = 0;    int bytessent = 0;    while (bytessent < count)    {        curcount = SSL_write(ssl,str,count-bytessent);        if (curcount < 0)        {            debug("send error");            return curcount;        }        bytessent = bytessent + curcount;        str += curcount;     }    return count;}int mysock_read_ssl(SSL *ssl,char *str,int size,int timeout){    if (NULL == str)    {        return -1;    }    char *cur = str;    char buff[1];    int count=0;    char lastread = 0;    int tmpcount = 0;    while (10 != lastread)    {        tmpcount = SSL_read(ssl,buff,1);        if (-1 == tmpcount)        {            debug("recv error");            return -1;        }        lastread = buff[0];        if ((count < size)&&(10 != lastread)&&(13!=lastread) )        {            count++;            *cur = lastread;            cur++;        }    }    if (count > 0)    {        *cur = 0;    }    return count;}#endif
原创粉丝点击