该网络编程之客户端与服务端程序模板支持:
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(0) int main(int argc, char **argv) { int sockfd; struct sockaddr_in servaddr; if(argc != 2) { //printf("usage: p2pcli <IPaddress> "); //exit(0); ERR_EXIT("usage: p2pcli <IPaddress> "); } sockfd = socket(AF_INET, SOCK_STREAM, 0); memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(5188); servaddr.sin_addr.s_addr = inet_addr(argv[1]); if(connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) { ERR_EXIT("connect"); } //communication char sendbuf[1024] = {0}; char recvbuf[1024] = {0}; 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, 0, sizeof(sendbuf)); memset(recvbuf, 0, sizeof(recvbuf)); } close(sockfd); return 0; }
服务端程序如下:
/************************************************************************* > 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(0) void do_service(int connfd) { //communication char recvbuf[1024]; while(1) { memset(recvbuf, 0, sizeof(recvbuf)); int ret = read(connfd, recvbuf, sizeof(recvbuf)); if(ret == 0) { printf("client close. "); break; } else if(ret == -1) { break; } else { fputs(recvbuf, stdout); write(connfd, recvbuf, ret); } } } int main() { int listenfd; if( (listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { ERR_EXIT("socket"); } struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(5188); servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //reuse address int on = 1; if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) { 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 connfd; //muti client pid_t pid; while(1) { if( (connfd = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen)) < 0 ) { ERR_EXIT("accept"); } printf("ip=%s, port=%d ", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port)); pid = fork(); if(pid == -1) { ERR_EXIT("fork"); } else if(pid == 0) { //child close(listenfd); do_service(connfd); exit(0); } else { close(connfd); } } close(connfd); close(listenfd); return 0; }