该网络编程之客户端与服务端程序模板支持:
1. 多客户端同时连接服务端,即服务程序可以同时为多个客户端服务;
2. 服务端支持套接字对重用,即即使处于TIME_WAIT状态,仍可支持服务端重启;
3. 服务端可以发现客户端是否已断开连接;
4. 支持客户端标准输入会显,服务端从标准输出显示客户端所输入内容。
程序如下,记下该模板以备再次使用:
客户端程序如下:
/*************************************************************************
> File Name: p2pcli.c
> Author: ma6174
> Mail: ma6174@163.com
> Created Time: Sun 05 Oct 2014 09:26:40 PM HKT
************************************************************************/ #include<stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h> #include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h> #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
}while() int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr; if(argc != )
{
//printf("usage: p2pcli <IPaddress> ");
//exit(0);
ERR_EXIT("usage: p2pcli <IPaddress> ");
} sockfd = socket(AF_INET, SOCK_STREAM, ); memset(&servaddr, , sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons();
servaddr.sin_addr.s_addr = inet_addr(argv[]); if(connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < )
{
ERR_EXIT("connect");
} //communication
char sendbuf[] = {};
char recvbuf[] = {};
while(fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
{
//send to server.
write(sockfd, sendbuf, strlen(sendbuf));
//read from server to display.
read(sockfd, recvbuf, sizeof(recvbuf)); //display
fputs(recvbuf, stdout);
memset(sendbuf, , sizeof(sendbuf));
memset(recvbuf, , sizeof(recvbuf));
}
close(sockfd);
return ;
}
服务端程序如下:
/*************************************************************************
> File Name: p2psrv.c
> Author: ma6174
> Mail: ma6174@163.com
> Created Time: Sun 05 Oct 2014 08:27:06 PM HKT
************************************************************************/ #include<stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h> #include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h> #define ERR_EXIT(m)\
do\
{\
perror(m);\
exit(EXIT_FAILURE);\
}while() void do_service(int connfd)
{
//communication
char recvbuf[];
while()
{
memset(recvbuf, , sizeof(recvbuf));
int ret = read(connfd, recvbuf, sizeof(recvbuf));
if(ret == )
{
printf("client close.\n");
break;
}
else if(ret == -)
{
break;
}
else
{
fputs(recvbuf, stdout);
write(connfd, recvbuf, ret);
}
}
} int main()
{
int listenfd;
if( (listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < )
{
ERR_EXIT("socket");
} struct sockaddr_in servaddr;
memset(&servaddr, , sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons();
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //reuse address
int on = ;
if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
{
ERR_EXIT("setsockopt");
} if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < )
{
ERR_EXIT("bind");
} if(listen(listenfd, SOMAXCONN) < )
{
ERR_EXIT("listen");
} struct sockaddr_in peeraddr;
socklen_t peerlen = sizeof(peeraddr);
int connfd; //muti client
pid_t pid;
while()
{
if( (connfd = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen)) < )
{
ERR_EXIT("accept");
} printf("ip=%s, port=%d\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port)); pid = fork();
if(pid == -)
{
ERR_EXIT("fork");
}
else if(pid == )
{
//child
close(listenfd);
do_service(connfd);
exit();
}
else
{
close(connfd); }
}
close(connfd);
close(listenfd);
return ;
}