简单socket
#pragma once #include <netinet/in.h> #include <unistd.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <netdb.h> #include <netinet/tcp.h> #include <sys/types.h> #include <linux/socket.h> #include "comhdr.h" #define CHECK_DWORD 0xaebecede #define INVALID_SOCKET (-1) #define SOCKET_ERROR (-1) //void sockInit(); //void sockClean(); BOOL sockCreateConnect(IN short nPort,OUT int *sock_srv); //服务端创建Socket BOOL sockWaitConnect(IN int sock_srv,OUT int *sock_con); //服务端等待连接(阻塞) BOOL sockToConnect(const char *szIp,short nPort,int *sock); //客户端去连接 int sockRcvMsg(IN int sock,OUT char *buf,IN int bufLen); //只收一次数据 int sockRcvMsgEx(IN int sock,OUT char *buf,IN int needLen); //收数据直至到needLen大小 int sockSndMsg(IN int sock,IN char *buf,IN int bufLen); //发送数据 void sockDestroy(IN int sock); //关闭socket //void sockInit() //{ // WSADATA wsaData; // WSAStartup(MAKEWORD(2, 2), &wsaData); //} //void sockClean() //{ // WSACleanup(); //} void sockSetOption(int sock) { int iReuseAddr = SO_REUSEADDR; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&iReuseAddr, sizeof(iReuseAddr)); //开启keepalive属性 int keepAlive = 1; setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive)); //连接在15秒内没有任何数据进行探测 int keepIdle = 15; setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle)); //探测发包时间间隔为5秒 int keepInterval = 5; setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval)); // 探测尝试的次数.如果第1次探测包就收到响应了,则后2次的不再发. //探测3次 int keepCount = 3; setsockopt(sock, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount)); } //服务端创建Socket BOOL sockCreateConnect(IN short nPort,OUT int *sock_srv) { int ret; sockaddr_in addrSrv; short ports = nPort; *sock_srv = socket(AF_INET, SOCK_STREAM, 0); if(*sock_srv == INVALID_SOCKET) { return FALSE; } addrSrv.sin_family = AF_INET; addrSrv.sin_addr.s_addr = htonl(INADDR_ANY); addrSrv.sin_port = htons(ports); ret = bind(*sock_srv,(sockaddr*)&addrSrv, sizeof(sockaddr)); if(ret == SOCKET_ERROR) { close(*sock_srv); return FALSE; } ret = listen(*sock_srv, SOMAXCONN); if(ret == SOCKET_ERROR) { close(*sock_srv); return FALSE; } int iReuseAddr = SO_REUSEADDR; setsockopt(*sock_srv, SOL_SOCKET, SO_REUSEADDR, (void *)&iReuseAddr, sizeof(iReuseAddr)); return TRUE; } //等待连接 BOOL sockWaitConnect(IN int sock_srv,OUT int *sock_con) { socklen_t sockSize; sockaddr_in addrClient; int sock_client; sockSize = sizeof(sockaddr); sock_client = accept(sock_srv,(sockaddr*)&addrClient,&sockSize); int iReuseAddr = SO_REUSEADDR; setsockopt(sock_client, SOL_SOCKET, SO_REUSEADDR, (void *)&iReuseAddr, sizeof(iReuseAddr)); sockSetOption(sock_client); /* DWORD chBuf; int ret = recv(sock_client, (char *)(&chBuf),sizeof(chBuf),0); if (ret == SOCKET_ERROR) { close(sock_client); //printf("sockCreateConnect : recv socket failed,error id : %u.\n",WSAGetLastError()); return FALSE; } if (CHECK_DWORD != chBuf) { //printf("sockCreateConnect : not my care.\n"); close(sock_client); return FALSE; } */ *sock_con = sock_client; return TRUE; } //客户端连接 BOOL sockToConnect(IN const CHAR* szIp,IN short nPort,OUT int *sock) { sockaddr_in addrSrv; const CHAR* ip = szIp; do { int ret; *sock = socket(AF_INET, SOCK_STREAM, 0); if (INVALID_SOCKET == *sock) { //printf("sockToConnect : socket create failed\n"); break; } if (szIp == NULL) { ip = "127.0.0.1"; } addrSrv.sin_addr.s_addr = inet_addr(ip); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(nPort); ret = connect(*sock, (sockaddr*)&addrSrv, sizeof(sockaddr)); if (ret == SOCKET_ERROR) { //printf("sockToConnect : socket connect failed\n"); break; } sockSetOption(*sock); /* DWORD inBuf = CHECK_DWORD; ret = send(*sock, (char *)&inBuf, sizeof(DWORD), 0); if (ret == SOCKET_ERROR) { //printf("sockToConnect : socket send failed\n"); break; } */ return TRUE; } while (0); if(INVALID_SOCKET != *sock) { close(*sock); *sock = INVALID_SOCKET; } return FALSE; } //收到一次就返回 int sockRcvMsg(IN int sock,OUT char *buf,IN int bufLen) { int iRet = recv(sock, (CHAR *)buf, bufLen, MSG_NOSIGNAL); if(iRet == 0 && errno != 0 && errno != EAGAIN) { iRet = SOCKET_ERROR; } return iRet; } //会等到收到needLen了以后才返回 int sockRcvMsgEx(IN int sock,IN char *data,IN int datalen) { int iRet; int iReaded = 0; fd_set rfd; for(;;) { iRet = recv(sock,(char *)data+iReaded,datalen-iReaded,MSG_NOSIGNAL); if (iRet == -1) { if(errno == EAGAIN) { FD_ZERO(&rfd); FD_SET(sock,&rfd); iRet = select(sock+1, &rfd, NULL, NULL, NULL); if (FD_ISSET(sock,&rfd) && iRet > 0) { continue; } else if (iRet == 0) { if (errno == 0) { continue; } else if (errno == EAGAIN) { continue; } else { iRet = SOCKET_ERROR; break; } } else if (iRet == -1) { iRet = SOCKET_ERROR; break; } } else { iRet = SOCKET_ERROR; break; } } else if(iRet == 0) { iRet = SOCKET_ERROR; break; } else { iReaded += iRet; if (iReaded == datalen) { iRet = iReaded; break; } } } return iRet; } //发送数据 int sockSndMsg(IN int sock,IN char *buf,IN int bufLen) { int iRet = send(sock,(char *)buf,bufLen,MSG_NOSIGNAL); if(iRet == 0 && errno != 0 && errno != EAGAIN) { iRet = SOCKET_ERROR; } return iRet; } //发送datelen大小的数据 int sockSndMsgEx(IN int sock,IN char *data,IN int datalen) { int iRet; int iWrited = 0; fd_set wfd; for(;;) { iRet = send(sock,(char *)data+iWrited,datalen-iWrited,MSG_NOSIGNAL); if (iRet == -1) { if(errno == EAGAIN) { FD_ZERO(&wfd); FD_SET(sock,&wfd); iRet = select(sock+1, NULL, &wfd, NULL, NULL); if (FD_ISSET(sock,&wfd) && iRet > 0) { continue; } else if (iRet == 0) { if (errno == 0) { continue; } else if (errno == EAGAIN) { continue; } else { iRet = SOCKET_ERROR; break; } } else if (iRet == -1) { iRet = SOCKET_ERROR; break; } } else { iRet = SOCKET_ERROR; break; } } else if(iRet == 0) { iRet = SOCKET_ERROR; break; } else { iWrited += iRet; if (iWrited == datalen) { iRet = iWrited; break; } } } return iRet; } //接收数据 void sockDestroy(IN int sock) { shutdown(sock,2); close(sock); }