网编(14):套接字和标准I/O

版权声明:转载请声明 https://blog.csdn.net/qq_40732350/article/details/89003772

标准I/O函数的优点

  • 标准I/O函数具有良好的移植性( PortabiJity )。
  • 标准I/O函数可以利用缓冲提高性能。

创建套接字时,操作系统将生成用于I/O的缓冲。此缓冲在执行TCP协议时发挥着非常重要的作用。此时若使用标准I/O函数,将得到额外的另一缓冲的支持,如图所示。

标准I/O函数的几个缺点

  • 不容易进行双向通信。
  • 有时可能频繁调用fllush 函数。
  • 需要以FILE结构体指针的形式返回文件描述符。

打开文件时,如果希望同时进行读写操作,则应以r+ 、W七a+模式打开。但因为缓冲的缘故,每次切换读写工作状态时应调用fllush
函数。这也会影响基于缓冲的性能提高。而且,为了使用标准I/0函数,需要FILE指针。而创建套接字时默认返回文件描述符,因此需要将文件描述符转化为FILE指针。

利用fdopen 函数转换为FILE 结构体指针

#include <stdio.h>
FILE* fdopen(int fildes, const char * mode);
//成功时返回转换的FILE 结构体指针,失败时返回NULL 。

#tildes 需要转换的文件描述符。
#mode   将要创建的FILE结构体指针的模式(mode)信息。

实例代码:

#include <stdio.h>
#include <fcntl.h>
int main(void)
{
	FILE *fp;
	int fd=open("data.dat", O_WRONLY | O_CREAT | O_TRUNC);
	if(fd==-1)
	{
		fputs("file open error", stdout);
		return -1;
	}
	fp=fdopen(fd, "w");
	fputs("Network C programming \n", fp);
	fclose(fp);
	return 0;
}

利用fileno 函数转换为文件描述符

#include <stdio.h>
int fileno(FILE * stream);
//成功时返回转换后的文件描述符,失败时返回-1 。

实例代码:

#include <stdio.h>
#include <fcntl.h>

int main(void)
{
	FILE *fp;
	int fd=open("data.dat", O_WRONLYjO_CREAT IO_TRUNC);
	if{fd==-1)
	{
		fputs("file open error", stdout);
		return -1;
	}

	printf("First file descriptor: %d \n", fd);
	fp=fdopen(fd, "w");
	fputs("TCP/IP SOCKET PROGRAMMING \n", fp);
	printf("Second file descriptor: %d \n", fileno(fp));
	fclose(fp);
	return 0;
}

基于套接字的标准I/O函数使用

服务器:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define TTL 64
#define BUF_SIZE 30
void error_handling(char *message);
int main(int argc, char *argv[])
{
	int serv_sock, clnt_sock;
	char message[BUF_SIZE];
	int str_len, i;

	struct sockaddr_in serv_adr;
	struct sockaddr_in clnt_adr;
	socklen_t clnt_adr_sz;
	FILE * readfp;
	FILE * writefp;
	if(argc!=2) {
		printf("Usage : %s <port>\n", argv[0]);
		exit(1);
	}

	serv_sock=socket(PF_INET, SOCK_STREAM, 0);
	if(serv_sock==-1)
		error_handling("socket() error");

	memset(&serv_adr, 0, sizeof(serv_adr));
	serv_adr.sin_family=AF_INET;
	serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
	serv_adr.sin_port=htons(atoi(argv[1]));

	if(bind(serv_sock, (struct sockaddr* )&serv_adr , sizeof(serv_adr))== -1 )
		error_handling("bind() error");
	if(listen(serv_sock, 5)==-1)
		error_handling("list en() e r ror");
	clnt_adr_sz=sizeof (clnt_adr ) ;

	for(i=0; i<5; i++)
	{
		clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz);
		if(clnt_sock==-1)
			error_handling("accept () error");
		else
			printf("Connected client %d \n", i+1);

		readfp=fdopen(clnt_sock, "r");
		writefp=fdopen(clnt_sock, "w");
		while(!feof(readfp))
		{
			fgets(message, BUF_SIZE, readfp);
			fputs(message, writefp);
			fflush(writefp);//清理空间
		}
		fclose(readfp);
		fclose(writefp);
	}
	close(serv_sock);
	return 0;
}

void error_handling(char *message)
{
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}

客户端:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define TTL 64
#define BUF_SIZE 30
void error_handling(char *message);
int main(int argc, char *argv[])
{
	int clnt_sock;
	char message[BUF_SIZE];
	int str_len, i;

	struct sockaddr_in clnt_adr;
	socklen_t clnt_adr_sz;
	FILE * readfp;
	FILE * writefp;
	if(argc!=3) {
		printf("Usage : %s <port>\n", argv[0]);
		exit(1);
	}

	clnt_sock=socket(PF_INET, SOCK_STREAM, 0);
	if(clnt_sock==-1)
		error_handling("socket() error");

	memset(&clnt_adr, 0, sizeof(clnt_adr));
	clnt_adr.sin_family=AF_INET;
	clnt_adr.sin_addr.s_addr=htonl(INADDR_ANY);
	clnt_adr.sin_port=htons(atoi(argv[2]));

	if(connect(clnt_sock, (struct sockaddr*)&clnt_adr, sizeof(clnt_adr))== - 1)
		error_handling("bind() error");
	
	readfp=fdopen(clnt_sock, "r");
	writefp=fdopen(clnt_sock, "w");

	while(1)
	{
		fputs("Input message(Q to quit) : ", stdout);
		fgets(message, BUF_SIZE, stdin);
		if(!strcmp(message,"q\n") || !strcmp(message, "Q\n" ))
			break;

		fputs(message, writefp);
		fflush(writefp);
		fgets(message, BUF_SIZE, readfp);
		printf("Message from server: %s", message);
	}
	fclose(readfp);
	fclose(writefp);
	
	close(clnt_sock);
	return 0;
}

void error_handling(char *message)
{
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}

运行结果:

#服务器
$ ./ser 9190
Connected client 1 

#客户端
$ ./cli 192.168.43.220 9190
Input message(Q to quit) : 123
Message from server: 123
Input message(Q to quit) : 456
Message from server: 456

猜你喜欢

转载自blog.csdn.net/qq_40732350/article/details/89003772