一、函数的准备和功能介绍
首先是 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);
//初始化 ssl
int 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