my_socket.c:
#include "my_socket.h"
int createTcpClient(const int serPort, const char* serIp)
{
int serFd = -1;
int ret;
struct sockaddr_in saddr;
serFd = socket(PF_INET, SOCK_STREAM, 0);
if (serFd < 0)
{
perror("socket");
return -1;
}
saddr.sin_family = AF_INET;
saddr.sin_port = htons(serPort);
inet_pton(AF_INET, serIp, &saddr.sin_addr.s_addr);
ret = connect(serFd, (struct sockaddr*)&saddr, sizeof(saddr));
if (ret < 0)
{
perror("connect");
if (serFd > 0)
{
close(serFd);
}
return -1;
}
return serFd;
}
int createTcpServer(const int serPort)
{
int serFd;
struct sockaddr_in serAddr;
struct sockaddr_in cliAddr;
int addrLen = sizeof(cliAddr);
int cliFd = -1;
char buffer[4096];
int iDataNum;
int ret = -1;
if ((serFd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket");
return 1;
}
bzero(&serAddr, sizeof(serAddr));
//初始化服务器端的套接字,并用htons和htonl将端口和地址转成网络字节序
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(serPort);
// ip可是是本服务器的ip,也可以用宏INADDR_ANY代替,代表0.0.0.0,表明所有地址
serAddr.sin_addr.s_addr = htonl(INADDR_ANY);
//对于bind,accept之类的函数,里面套接字参数都是需要强制转换成(struct sockaddr
//*) bind三个参数:服务器端的套接字的文件描述符,
int opt = 1;
setsockopt(serFd, SOL_SOCKET, SO_REUSEADDR, (const void*)&opt, sizeof(opt));
if (bind(serFd, (struct sockaddr*)&serAddr, sizeof(serAddr)) < 0)
{
perror("connect");
return 1;
}
//设置服务器上的socket为监听状态
if (listen(serFd, 5) < 0)
{
perror("listen");
return 1;
}
printf("Listening on port: %d\n", serPort);
fd_set serSet, rserSet;
FD_ZERO(&serSet);
FD_SET(serFd, &serSet);
int maxfd = serFd;
struct timeval tv0;
while (1)
{
rserSet = serSet;
printf("wait select ....\n");
tv0.tv_sec = 5;
tv0.tv_usec = 0;
ret = select(maxfd + 1, &rserSet, NULL, NULL,&tv0); //对读进行操作等待(NULL时无限等待)
if (ret == 0)
{
printf("select ret == 0 ....\n");
continue;
}
if (ret < 0)
{
perror("select");
sleep(1);
continue;
}
if (FD_ISSET(serFd, &rserSet))
{
if (cliFd > 0)
{
printf("client(IP:%s port:%d) is broken ...\n",inet_ntoa(cliAddr.sin_addr),htons(cliAddr.sin_port));
close(cliFd);
cliFd = -1;
}
cliFd = accept(serFd, (struct sockaddr*)&cliAddr, (socklen_t*)&addrLen);
if (cliFd < 0)
{
perror("accept");
continue;
}
printf("\nrecv cliFd data...\n");
// inet_ntoa ip地址转换函数,将网络字节序IP转换为点分十进制IP
//表达式:char *inet_ntoa (struct in_addr);
printf("client(IP:%s port:%d) connect ...\n",inet_ntoa(cliAddr.sin_addr),htons(cliAddr.sin_port));
if (cliFd > maxfd)
{
maxfd = cliFd;
}
FD_SET(cliFd, &serSet);
}
else
{
if (cliFd < 0)
{
continue;
}
memset(buffer, 0, 4096);
iDataNum = recv(cliFd, buffer, 4096, MSG_DONTWAIT);
if (iDataNum <= 0)
{
FD_CLR(cliFd, &serSet);
if (iDataNum < 0)
{
perror("recv");
}
else
{
if (cliFd > 0)
{
printf("client(IP:%s port:%d) disconnect ...\n",inet_ntoa(cliAddr.sin_addr),htons(cliAddr.sin_port));
close(cliFd);
}
cliFd = -1;
}
continue;
}
else
{
printf("buffer form cli: %s\n", buffer);
}
}
}
if(serFd > 0)close(serFd);
if(cliFd > 0)close(cliFd);
return 0;
}
ser.c:
#include "my_socket.h"
int main()
{
createTcpServer(8888);
}
cli.c:
#include "my_socket.h"
int main()
{
int serFd = createTcpClient(8888, "127.0.0.1");
char buf[] = "abcdefg";
int ret = -1;
while (1)
{
ret = send(serFd, buf, sizeof(buf), 0);
if (ret < 0)
{
perror("send");
break;
}
sleep(1);
}
if(serFd > 0)close(serFd);
}