socket编程之时间回射服务器

时间:2021-06-10 17:47:13

使用到的函数:

// 返回值:读到的字节数,若已到文件尾,返回0;若出错,返回-1
ssize_t read(int fd, void *buf, size_t nbytes);
// 返回值:若成功,返回已写的字节数;若出错,返回-1
ssize_t write(int fd, const void *buf, size_t nbytes);
int socket(int socket_family, int socket_type, int protocol);
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
// backlog指定系统内核允许在这个监听描述符上排队的最大客户连接数
int listen(int sockfd, int backlog); int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
struct sockaddr_in {
    __uint8_t    sin_len;
    sa_family_t  sin_family;
    in_port_t    sin_port;
    struct       in_addr sin_addr;
    char         sin_zero[8];
};

 客户端程序:

socket编程之时间回射服务器socket编程之时间回射服务器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#define MAXLINE 4096

int main(int argc, char **argv) {
    
    int sockfd, n;
    char recvline[MAXLINE + 1];
    struct sockaddr_in servaddr;
    
    if (argc != 2) {
        perror("Usage: a.out <IPaddress>");
        exit(1);
    }
    
    if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket error");
        exit(1);
    }
    
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(13);  /* daytime server */
    if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {
        printf("inet_pton error for %s\n", argv[1]);
        exit(1);
    }
    
    if (connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
        perror("connect error");
        exit(1);
    }
    
    while ( (n = read(sockfd, recvline, MAXLINE)) > 0) {
        recvline[n] = 0;
        if (fputs(recvline, stdout) == EOF) {
            perror("fputs error");
            exit(1);
        }
    }
    
    if (n < 0) {
        perror("read error");
        exit(1);
    }
    
    exit(0);
}
View Code

服务器程序:

socket编程之时间回射服务器socket编程之时间回射服务器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <time.h>

#define MAXLINE 4096
#define LISTENQ 10

int main(int argc, char **argv) {
    
    int listenfd, connfd;
    struct sockaddr_in servaddr;
    char buff[MAXLINE];
    time_t ticks;
    
    if ( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket error");
        exit(1);
    }
    
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(13);  /* daytime server */
    
    if ( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
        perror("bind error");
        exit(1);
    }
    
    if ( listen(listenfd, LISTENQ) < 0) {
        perror("listen error");
        exit(1);
    }
    
    for ( ; ; ) {
        if ( (connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) < 0) {
            perror("accept error");
            exit(1);
        }
        
        ticks = time(NULL);
        snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
        write(connfd, buff, strlen(buff));
        close(connfd);
    }
}
View Code

 

PS:

close和shutdown的区别:

(1) close把描述符的引用计数减1,仅在该计数变为0时才关闭套接字。shutdown不管引用计数,直接激发TCP的正常连接终止序列。

(2) close终止读和写两个方向的数据传输,shutdown可以只关闭一个方向。