Pro_1_UNIX下最简单的C_S程序_2016_8_5


service:

/*
 * 抄自《UNIX网络编程:卷1》, 稍作修改。
 * 仅仅用于学习目的。学无止境,进步每一天。
 *  
 * slickedit编辑。 
 *  
 * 254008829@qq.com 
 *  
 */

#include <stdio.h>
#include <stdlib.h> /* exit */ 
#include <string.h> /* bzero */
#include <unistd.h> /* read */
#include <netinet/in.h> /* strut sockaddr_in */
#include <arpa/inet.h>  /* inet_pton */
#include <time.h>
#include <errno.h> /* errno */

#define	MAXLINE 65507
#define LISTEN_MAX 10

#define FUNC_RET(func, val) \
    do { \
        int rv; \
        if ( (rv=func) < 0) { \
            printf("LINE = %d, error str: %s\n", __LINE__, strerror(errno)); \
            exit(-1); \
        } \
        val = rv; \
    } while (0);

int 
main(int argc, char **argv)
{
    int sockfd, connfd, ret;
    char buf[MAXLINE];
    struct sockaddr_in servaddr;

    FUNC_RET(socket(AF_INET, SOCK_STREAM, 0), sockfd);
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(13);
    /* INADDR_ANY,当服务器有多个网络接口的时候, 服务器可以从任意网络接口上接收来自客服端的消息 */
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    /* 将生成的sockfd与设置的servaddr绑定 */
    FUNC_RET(bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)), ret);
    /* listen把该套接字转化成一个监听套接字 */
    FUNC_RET(listen(sockfd, LISTEN_MAX), ret);

    while (1) {
        time_t ticks;
        /* accept函数执行后服务进程会陷入睡眠,等待某个客户端连接,并被内核接受, 唤醒进程。 
        TCP连接使用的是三次握手, 握手完成后accept返回, 它返回的是新的描述符。称之为已连接描述符,
        服务端用这个新的connfd与新近连接的那个客户程序通信 */
        FUNC_RET(accept(sockfd, (struct sockaddr *)NULL, NULL), connfd);
        ticks = time(NULL);
        snprintf(buf, sizeof(buf), "%.24s\r\n", ctime(&ticks));
        write(connfd, buf, strlen(buf));
        close(connfd);
    }

    exit(0);
}

/*
在ubuntu下编译: gcc daytimetcpserv.c -o service 
运行: sudo ./service 
 */

client:

/*
 * 抄自《UNIX网络编程:卷1》 
 * 仅仅用于学习目的  
 *  
 * slickedit编辑。 
 *  
 * 254008829@qq.com 
 *  
 */

#include <stdio.h>
#include <stdlib.h> /* exit */ 
#include <string.h> /* bzero */
#include <unistd.h> /* read */
#include <netinet/in.h> /* strut sockaddr_in */
#include <arpa/inet.h>  /* inet_pton */
#include <errno.h> /* errno */

#define	MAXLINE 65507

#define FUNC_RET(func, val) \
    do { \
        int rv; \
        if ( (rv=func) < 0) { \
            printf("LINE = %d, error str: %s\n", __LINE__, strerror(errno)); \
            perror("FUNC_RET"); \
            exit(-1); \
        } \
        val = rv; \
    } while (0);

int 
main(int argc, char **argv)
{
    int sockfd, n, ret;
    char recvline[MAXLINE + 1];
    struct sockaddr_in servaddr;

    if (argc != 2) {
        printf("usage: %s ip_addr\n", argv[0]);
        exit(0);
    }

    /*
     * socket函数是创建一个socket套接字,第一个参数是AF_INET表明是IPV4协议, SOCK_STREAM表明是传送的是字节流。 
     * 第三个参数为零, 则默认AF_INET和SOCK_STREAM组合是TCP协议。 
     */
    FUNC_RET(socket(AF_INET, SOCK_STREAM, 0), sockfd);

    bzero(&servaddr, sizeof(servaddr)); // 将auto变量servaddr清零。
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(13); // 13是时间获取服务器众所周知的端口。

    /* 将十进制点分式的IP地址转换成网络格式 */
    FUNC_RET(inet_pton(AF_INET, argv[1], &servaddr.sin_addr), ret);
    /* connect函数应用于TCP套接字时候, 将sockfd与servaddr结构指定的服务器建立一个TCP连接 */
    FUNC_RET(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)), ret);
    /* 从连接的服务器处读取内容 */
    while ( (n=read(sockfd, recvline, MAXLINE)) > 0) {
        recvline[n] = 0;
        if (fputs(recvline, stdout) == EOF) {
            perror("fputs error:");
            exit(0);
        }
    }

    if (n < 0) {
        perror("read error: ");
    }

    exit(0);
}

/*
在ubuntu下编译生成client可执行文件。 
等服务端先运行后,执行: ./client 127.0.0.1 
结果为: 
    Sun Aug  7 11:33:42 2016
 
127.0.0.1这个IP是本地回环IP, client程序连接这个IP表明是和自己本机通信。 
 */



 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值