#include "ccnet.h"
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>
#include <signal.h>
#include <errno.h>
#include <limits.h>
#include <fcntl.h>
//连接服务器
static int
Connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen)
{
assert(serv_addr != NULL);
return connect(sockfd, serv_addr, addrlen);
}
//关闭服务器
int Close(int fd)
{
return close(fd);
}
//连接服务器
// 入参数:IP, port,timeout
int CCConnectO(const char *host, int port, int *timeout, const char *name)
{
char buf[1024];
fd_set rset, wset;
struct hostent he, *p;
struct sockaddr_in sin;
socklen_t len = 0;
int sock = -1, ret = 0, err = 0, flags = 0, on = 1;
struct timeval t;
assert(host != NULL);
if (*timeout < 0){
*timeout = 0;
}
int old_timeout = *timeout;
// invalid server
if (host[0] == 0 || port == 0) {
return -1;
}
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
LOG_WARN( "cannot create socket while connecting to %s(%s:%d)",name, host, port);
return -1;
}
bzero(&sin, sizeof(sin));
sin.sin_addr.s_addr = inet_addr(host);
if ((sin.sin_addr.s_addr) == INADDR_NONE) { /* host is not numbers-and-dots ip address */
ret = gethostbyname_r(host, &he, buf, sizeof(buf), &p, &err);
if (ret < 0) {
LOG_WARN("cannot resolve hostname while connecting to %s(%s:%d)",name, host, port);
close(sock);
return -1;
}
memcpy(&sin.sin_addr.s_addr, he.h_addr, sizeof(sin.sin_addr.s_addr));
}
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
flags = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flags | O_NONBLOCK);
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
ret = Connect(sock, (struct sockaddr *) &sin, sizeof(sin));
if (ret == 0) {
fcntl(sock, F_SETFL, flags);
LOG_INFO("connect to %s(%s:%d) OK",name, host, port);
return sock;
} else {
if (errno != EINPROGRESS) { /* cannot connect to the host */
LOG_WARN("fail while connecting to %s(%s:%d)",name, host, port);
close(sock);
return -1;
}
FD_ZERO(&rset);
FD_SET(sock, &rset);
wset = rset;
t.tv_sec = *timeout / 1000000, t.tv_usec = *timeout % 1000000;
ret = select(sock + 1, &rset, &wset, NULL, &t);
if (t.tv_sec * 1000000 + t.tv_usec < 10)
t.tv_sec = 0, t.tv_usec = 0;
*timeout = t.tv_sec * 1000000 + t.tv_usec;
if (ret == 0) {
LOG_WARN("timeout(%d us) while connecting to %s(%s:%d)",old_timeout, name, host, port);
close(sock);
return -1;
}
if (FD_ISSET(sock, &rset) || FD_ISSET(sock, &wset)) {
len = sizeof(err);
ret = getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &len);
if (ret < 0) {
if (err){
errno = err;
}
LOG_WARN("getsockopt fail while connecting to %s(%s:%d)", name, host, port);
close(sock);
return -1;
}
if (err) {
errno = err;
LOG_WARN("sockselect fail while connecting to %s(%s:%d)", name, host, port);
close(sock);
return -1;
}
fcntl(sock, F_SETFL, flags);
LOG_INFO("connect to %s(%s:%d) OK", name, host,port);
return sock;
} else {
LOG_WARN("select fail while connecting to %s(%s:%d)", name,host, port);
close(sock);
return -1;
}
}
return -1;
}
{
int ret;struct timeval t;fd_set wset;ssize_t nleft, nwrite;char *ptr;
if (*timeout < 0)
*timeout = 0;
int old_timeout = *timeout;
// invalid sock
if (sock < 0) {
LOG_WARN("find invalid sock while write to %s:%d",name, sock);
return -1;
}
nleft = len;nwrite = 0;ptr = (char *) buf;t.tv_sec = *timeout / 1000000;t.tv_usec = *timeout % 1000000;
while (nleft > 0) {
// select socket
FD_ZERO(&wset);FD_SET(sock, &wset);
ret = select(sock + 1, NULL, &wset, NULL, &t);
if (t.tv_sec * 1000000 + t.tv_usec < 10)
t.tv_sec = 0, t.tv_usec = 0;
if (ret <= 0) {
if (ret != 0)
LOG_WARN("select fail while write to %s:%d", name, sock);
else
LOG_WARN("timeout(%d us) while write to %s:%d",old_timeout, name, sock);
return -1;
}
// write data
LOG_INFO("Write %s to %d with %d nleft",ptr, sock, nleft);
nwrite = write(sock, ptr, nleft);
if (nwrite < 0) {
if (errno == EINTR) {
continue;
}
LOG_WARN("write fail to %s:%d", name, sock);
break;
} else if (nwrite == 0) {
LOG_WARN("write fail to %s:%d(disconnect)", name, sock);
break;
}
ptr += nwrite;
nleft -= nwrite;
}
*timeout = t.tv_sec * 1000000 + t.tv_usec;
/* return the length of data read from server */
LOG_INFO("write %d bytes(want %d bytes) to %s:%d %s",len - nleft, len, name, sock, (nleft == 0) ? "OK" : "FAIL");
return (len - nleft);
}