unix网络编程笔记四

fgets和fputs函数

#include<stdio.h>
char *fgets(char *buf,int n,FILE *fp);
				成功返回buf,失败或读取到文件末尾返回NULL

这个函数的作用便是在一个文件中读取一行,有三个参数第一个表示读取到数据存放的缓冲区,第二个参数为最大读取的个数,第三个表示文件标识符。

读取一行表示当读取到换行符时会在换行符的后面添加一个null,并返回,当没有读取到换行符但是已经读取到n-1一个字符时会在第n个位置添加一个null字符,表示字符串的结束。

根据fgets的特点来使用read函数来编写一个readline函数。

ssize_t readline(int fd,char * buf,size_t maxlen)
{
	ssize_t n,rc;
	char *ptr,c;
	ptr=buf;
	for(n=1;n<maxlen;++n)
	{
	again:
		if((rc=read(fd,&c,1))==1)
		{
			*ptr++=c;
			if(c=='\n')
				break;
		}	
		else if(rc==0)
		{
			*ptr=0;
			return n-1;
		}
		else
		{
			if(errno==EINTR)
				goto again;
			return -1;    //表示出错
		}
	}
	*ptr=0;
	return n;
}

函数成功返回读到的字节数,失败返回-1;

#include<stdio.h>
int fputs(char *buf,FILE *fp);
		成功返回大于0的值,失败返回-1

这个函数是将buf缓冲区里的内容放入fp指向的文件里,这个函数时以null结束的,并不是判断换行符的。

feof和ferror函数

#include<stdio.h>
int ferror(FILE *fp);
int feof(FILE *fp);
	成功返回真,失败返回假

这两个函数的作用是判断一个FILE对象是否出现错误的,在FILE对象里存放有两个标志位,一个是文件结束标志,另一个是文件出错标志,常常使用这两个函数来判断文件是否出错。

进行改写一个fgets函数

char *Fgets(char *buf,int n,FILE *fp)
{
	char *p;
	if((p=fgets(buf,n,fp))==NULL)
	{
		if(feof(fp))
		{
			printf("fgets error\n");
			return 	NULL;
		}   //表示出错
		else
			return NULL;
	}
	return p;   //成功返回buf
}

分析:因为fgets到文件末尾和出错都会返回NULL,因此需要使用feof来判断是否出错。

下面是一个回射的程序
server

#include"unq.h"
#include"fun.h"
void str_echo(int fd);
int main()
{
int listenfd,newfd;
struct sockaddr_in addr;
addr.sin_port=htons(port);
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=htonl(INADDR_ANY);
listenfd=Socket(AF_INET,SOCK_STREAM,0);
Bind(listenfd,(struct sockaddr *)&addr,sizeof(addr));
Listen(listenfd,5);
while(1)
{
        int pid;
        newfd=Accept(listenfd,NULL,NULL);
        if((pid=fork())<0)
        {
                printf("fork error\n");
                return 0;
        }
        if(pid==0)
        {
                close(listenfd);
                str_echo(newfd);
        }
        else
        {
                close(newfd);
        }
}

}

这个服务器端和回射的操作是str_echo函数
str_echo函数

void str_echo(int fd)
{
	char buf[max];
	int n;
	again:
	while((n=read(fd,buf,max))>0)
	{
		write(fd,buf,n);
	}
	if(n<0&&errno==EINTR)
		goto again;
	else if(n<0)
	{
		printf("read error\n");
		exit(0);
	}
}

这个函数是将客户发过来的信息再发送给客户,write将read的返回值作为字符串的长度写入,当read返回为-1时可能是一个中断,因此做了一个判断,如果是一个中断则回到while继续执行。

下面是一个客户端的程序。
client

#include"unq.h"
#include"fun.h"
void str_cli(FILE *fp,int sockfd);
int main()
{
int fd;
struct sockaddr_in seraddr;
seraddr.sin_port=htons(port);
seraddr.sin_family=AF_INET;
seraddr.sin_addr.s_addr=inet_addr("127.0.0.1");
fd=Socket(AF_INET,SOCK_STREAM,0);
Connect(fd,(struct sockaddr *)&seraddr,sizeof(seraddr));
str_cli(fd,sockfd);
return 0;
}

其中str_cli函数是和服务器交互的程序。

str_cli

void str_cli(FILE *fp,int sockfd)
{
	char *p;
	char recvline[max],sendline[max];
	while((p=Fgets(fp,sendline,max))!=NULL)
	{
		write(sockfd,sendline,strlen(sendline));
		readline(sockfd,recvline,max);
		Fputs(recvline,stdout);
	}
}

成功返回

  1. 当客户端输入EOF时表示结束,fgets读取到文件结束返回NULL,则客户端程序结束,关闭套接字。
  2. 客户端向服务器端发送FIN,服务器read接收到EOF因此返回0,会结束服务器子进程,发送FIN对客户端,客户端对服务器进行响应,结束。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值