网络编程学习笔记(批量输入)
服务器端:
客户端读到EOF时,退出关闭套接字,导致输出的与输入的不一致(服务端显示的多于客户端显示的),在客户端读到EOF时,只是关闭客户端的写
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>#define SIN_PORT 9999
#define BUFLEN 256void str_echo(int fd);void sig_child(int signo)
{pid_t pid;int stat;while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) {printf("pid %d terminated
", pid);}}int main(int argc, char **argv)
{int listenfd, connfd;pid_t child;struct sockaddr_in servaddr;char buf[BUFLEN];time_t ticks;listenfd = socket(AF_INET, SOCK_STREAM, 0);if (listenfd < 0) {printf("socket error :%s
", strerror(errno)); return -1;}servaddr.sin_family = AF_INET;servaddr.sin_port = htons(SIN_PORT);servaddr.sin_addr.s_addr = htonl(INADDR_ANY);signal(SIGCHLD, sig_child);if (bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {printf("bind error:%s
", strerror(errno));close(listenfd);return -1;}if (listen(listenfd, 3) < 0) {printf("listen error:%s
", strerror(errno));close(listenfd);return -1;}struct sockaddr_in clientaddr;int len;for (;;) {len = sizeof(clientaddr);connfd = accept(listenfd, (struct sockaddr*)&clientaddr, &len);if (connfd < 0) {printf("accept error:%s
", strerror(errno));close(listenfd);return -1;}if ((child = fork()) == 0) {close(listenfd);str_echo(connfd);return 0;}close(connfd);}return 0;
}size_t readn(int fd, void *ptr, size_t n)
{char *p = ptr;size_t nleft = n;size_t nread;while (nleft > 0) {if ((nread = read(fd, p, nleft)) < 0) {if (errno == EINTR) nread = 0;else return -1;} else if (nread == 0) break;nleft -= nread;p += nread;}return n - nleft;
}size_t readline(int fd, void *ptr, size_t maxsize)
{char *p = ptr;size_t rc, n;char c;for (n = 1; n < maxsize; n++) {
again:if ((rc = read(fd, &c, 1)) == 1) {*p++ = c;if (c == '
') break;} else if (rc == 0) {if (n == 1) return 0;else break;} else {if (errno == EINTR) goto again;return -1;}}*p = 0;return n;
}size_t writen(int fd, void *ptr, size_t n)
{char *p = ptr;size_t nleft = n, nwriten;while (nleft > 0) {if ((nwriten = write(fd, p, nleft)) <= 0) {if (errno == EINTR) nwriten = 0;else return -1;}p += nwriten;nleft -= nwriten;}return n;
}void str_echo(int fd)
{char recvline[BUFLEN];int n;for (;;) {if ((n = readline(fd, recvline, BUFLEN)) == 0) return;printf("received buf=%s", recvline);writen(fd, recvline, n);}
}
客户端:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>#define SIN_PORT 9999
#define BUF_LEN 256
#define max(a, b) ((a) > (b) ? (a) : (b))size_t readline(int fd, void *ptr, int maxsize)
{char *p = ptr;char c;int rc;int n;for (n = 1; n < maxsize; n++) {again:if ((rc = read(fd, &c, 1)) == 1) {*p++ = c;if (c == '
') break; } else if (rc == 0) {if (n == 1) return 0;else break;}else {if (errno == EINTR) goto again;else return -1;}}*p = 0;return n;
}size_t readn(int fd, void *ptr, size_t n)
{char *p = ptr;int nleft = n;int nread;while (nleft > 0) {if ((nread = read(fd, p, nleft)) < 0) {if (errno == EINTR) nread = 0;else return -1;} else if (nread == 0) break;nleft -= nread;p += nread;}return n - nleft;
}size_t writen(int fd, void *ptr, size_t n)
{size_t nwriten;size_t nleft = n;char *p = ptr;while (nleft > 0) {if ((nwriten = write(fd, p, nleft)) <= 0) {if (errno == EINTR) nwriten = 0;else return -1;}nleft -= nwriten;p += nwriten;}return n;
}void str_cli(FILE *file, int fd)
{char recvline[BUF_LEN], sendline[BUF_LEN];int maxfdp1;fd_set fdset;int ret;int stdineof = 0;FD_ZERO(&fdset);for(;;) {if (stdineof == 0)FD_SET(fileno(file), &fdset);FD_SET(fd, &fdset);maxfdp1 = max(fileno(file), fd) + 1;ret = select(maxfdp1, &fdset, NULL, NULL, NULL); if (ret <= 0) {continue;}//printf("ret=%d
", ret);if (FD_ISSET(fd, &fdset)) {if (readline(fd, recvline, BUF_LEN) == 0) {if (stdineof == 1)return;else {printf("readline error:%s
", strerror(errno));return;}}fputs(recvline, stdout);} if (FD_ISSET(fileno(file), &fdset)) {memset(sendline, 0x00, sizeof(sendline));if (fgets(sendline, BUF_LEN, file) == NULL) {//printf("fgets error:%s
", strerror(errno));stdineof = 1;shutdown(fd, SHUT_WR);FD_CLR(fileno(file), &fdset);continue;}//printf("len=%d
", strlen(sendline));writen(fd, sendline, strlen(sendline));} }
}int main(int argc, char** argv)
{struct sockaddr_in serveraddr;int sockfd;#ifndef ONLINE_JUDGEfreopen("6.4Client.c", "r", stdin);
#endifsockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0) {printf("socket error:%s
", strerror(errno));return -1;} serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(SIN_PORT);if (inet_pton(AF_INET, argv[1], &serveraddr.sin_addr) != 1) {printf("inet_pton error:%s
", strerror(errno));close(sockfd);return -1;}if (connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0) {printf("connect error:%s
", strerror(errno));close(sockfd);return -1;}str_cli(stdin, sockfd);exit(0);}
客户端读到EOF时,退出关闭套接字,导致输出的与输入的不一致(服务端显示的多于客户端显示的),在客户端读到EOF时,只是关闭客户端的写