TCP服务器实现2
/*
服务端
*/
//定义一个错误的宏定义函数
#define ERR_EXIT(m) \
do \
{ \
perror(m);
exit(EXIT_FAILURE);
} while(0);
void do_service(int conn)
{
//获取发送数据
char recvbuf[1024];
while(1)
{
memset(recvbuf, 0 , sizeof(recvbuf));
int ret = read(conn, recvbuf, sizeof(recvbuf)); //读取数据
if(ret == 0)
{
//关闭了链接
printf("client_close\n");
break;
}else if(red == -1)
{
ERR_EXIT("read");
}
fputs(recvbuf, stdout); //输出
write(conn, recvbuf, ret);
}
//close(conn); //关闭链接
//close(listenfd); //关闭监听
}
int main(void)
{
/* code */
int listenfd;
//AF_INET IPV4
//SOCK_STREAM tcp
if((listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
ERR_EXIT("socket");//返回错误信息
}
struct sockaddr_in servaddr; //
memset(&servaddr, 0, sizeof(servaddr)); //设置0值
servaddr.sin_family = AF_INET; //设置数据类型
servaddr.sin_port = htons(5188); //设置端口号
servaddr.sin_addr.s_addr = htonl(INARRF_ANT); // 0.0.0.0
int on = 1;
if((setsockopt(listenfd, (struct sockaddr*) &servaddr, sizeof(on))) < 0) //设置套接口的选项。
{
ERR_EXIT("setsockopt");//返回错误信息
}
//绑定
if(bind(listenfd, (struct sockaddr*) &servaddr, sizeof(servaddr)) < 0))
{
ERR_EXIT("bind");//返回错误信息
}
//监听
if(listen(listenfd, SOMAXCONN < 0))
ERR_EXIT("listen");//返回错误信息
//声明存客户端的地址信息结构体
struct sockaddr_in peeraddr;
socklen_t peerlen = sizeof(peeraddr);
//获取链接客户端的信息
int conn;
pid_t pid;
while(1)
{
if(conn = accept(listenfd, (struct sockaddr*) &peeraddr) < 0)
{
ERR_EXIT("accept");
}
//打印链接客户信息
printf("ip=%s port=%s\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port));
//返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程标记;否则,出错返回-1。
pid = fork();
if(pid == -1)
ERR_EXIT("fork"); //创建失败
//子进程
if(pid == 0)
{
//conn 处理链接
close(listenfd); // 关闭监听
do_service(conn);
exit(EXIT_SUCCESS); //关闭
}else{
//父线程进行监听
close(conn);
}
}
return 0;
}
源码:
01_2.c