现在的位置: 首页 > 综合 > 正文

UNIX网络编程(10)–TCP 回射服务器程序和客户程序

2013年10月12日 ⁄ 综合 ⁄ 共 2214字 ⁄ 字号 评论关闭

一个简单的回射服务器的步骤
1.客户端从标准输入读入一行文本,并写给服务器。
2.服务器端从网络输入读入这行文本,并返回给客户
3.客户端从网络输入读入这行反射文本,并显示在标准输出上。

如图:

服务器程序:

#include	"unp.h"

int
main(int argc, char ** argv)
{
    int         listenfd,connfd;
    struct      sockaddr_in cliaddr,servaddr;
    pid_t       childpid;
    socklen_t   clilen;

    listenfd = Socket(AF_INET, SOCK_STREAM, 0);
    bzero(&servaddr, sizeof(servaddr));

    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);//#define	SERV_PORT		 9877
    Bind(listenfd, (SA *)&servaddr, sizeof(servaddr));
    Listen(listenfd, LISTENQ);
    for( ; ; )
    {
        clilen = sizeof(cliaddr);
        connfd = Accept(listenfd, (SA *)&cliaddr, &clilen);
        if((childpid = Fork()) == 0)
        {
            Close(listenfd);
            str_echo(connfd);
            exit(0);
        }
        Close(connfd);
    }
}

str_echo.c

#include	"unp.h"

void
str_echo(int sockfd)
{
    ssize_t n;
    char    buf[MAXLINE];//#define	MAXLINE		4096

again:
    while( (n = read(sockfd,buf,MAXLINE)) > 0)
        Writen(sockfd,buf,n);
    if(n<0 && errno == EINTR)
        goto again;
    else if (n<0)
        err_sys("str_echo:read error");
}

客户端程序:

#include "unp.h"
#define DEST_IP "127.0.0.1"

int
main(int argc, char ** argv)
{
    int         sockfd;

    struct      sockaddr_in servaddr;

    sockfd = Socket(AF_INET, SOCK_STREAM, 0);

    bzero(&servaddr, sizeof(struct sockaddr_in));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(SERV_PORT);

    Inet_pton(AF_INET, DEST_IP, &servaddr.sin_addr);
    Connect(sockfd, (SA *)&servaddr, sizeof(servaddr));

    str_cli(stdin,sockfd);
    Close(sockfd);
    exit(0);
}

//lib/str_cli.c

//lib/str_cli.c
#include    "unp.h"

void
str_cli(FILE *fp,int sockfd)
{
    char sendline[MAXLINE],recvline[MAXLINE];
    while(Fgets(sendline,MAXLINE,fp) != NULL)
    {
        Writen(sockfd,sendline,strlen(sendline));
        if(Readline(sockfd,recvline,MAXLINE) == 0)
            err_quit("str_cli :server terminated prematually");
        Fputs(recvline,stdout);
    }
}

其中,writen,readline函数参见博客:

http://blog.csdn.net/kuzuozhou/article/details/7386666

 

fgets的用法:

fget函数的原型如下:char *fgets (char *buf, int n, FILE *fp)

功能:从文件流读取一行,送到缓冲区,使用时注意以下几点:

1.当遇到换行符或者缓冲区已满,fgets就会停止,返回读到的数据,

注意的是不能用fgets读二进制文件,因为fgets会把二进制文件当成文本文件来处理,这势必会产生乱码。

2.每次调用,fgets都会把缓冲区的最后一个字符设为 \0,这意味着最后一个字符不能用来存放需要的数据,

   所以如果有一行,含有 LINE_SIZE 个字符(包括换行符),要想把这行读入缓冲区,请把参数 n 设为 LINE_SIZE+1

  多留一个位置存储 \0

3. 由结论1可推出:给定参数n,fgets只能读取n-1个字符(包括换行符),如果有一行超过n-1个字符,

   那么fgets返回一个不完整的行,也就是说,只读取该行的前n-1个字符,但是,缓冲区总是以 \0 字符结尾,

   对fgets的下一次调用会继续读该行。

代码:

FILE* fp = fopen(argv[1], "r");
char buf[200];
while(fgets(buf, 200, fp) != NULL) {     /* 每行的字符不能超过199(包括换行符)才能正常工作 */
    printf("%s",buf);
}

抱歉!评论已关闭.