tcp标准io简介 recv/send、readv/writev、recvmsg/sendmsg

目录

一:IO函数原型

二:具体的实例如下:



一:IO函数原型

#include <sys/types.h>
#include <sys/socket.h>

ssize_t recv(int s, void *buf, size_t len, int flags);
ssize_t send(int s, const void *buf, size_t len, int flags);

#include <sys/uio.h>
ssize_t readv(int s, struct iovec *vector, int conut);
ssize_t writev(int s, const struct iovec *vector, int conut);

struct iovec {
    void *iov_base;    /*向量的缓冲区地址*/
    size_t iov_len;    /*大小, 字节*/
};

#include <sys/types.h>
#include <sys/socker.h>
ssize_t recvmsg(int s, struct msghdr *msg, int flags);
ssize_t recvmsg(int s, const struct msghdr *msg, int flags);

struct msghdr {
    void *msg_name;        /*可选地址*/
    socklen_t msg_namelen;
    struct iovec *msg_iov;  /*接收数据的数组*/
    size_t msg_iovlen;
    void *msg_control;      
    socklen_t msg_controllen;
    int msg_flags;   
}

                                                               flags的值及含义

含义
MSG_DONTWAIT 非阻塞操作
MSG_ERRQUEUE错误消息从套接字错误队列接收
MSG_OOB接收外带数据
MSG_PEEK查看数据,不进行数据缓冲区的清空
MSG_TRUNC返回所有数据, 及指定的缓冲区过小,多余的数据会被丢弃
MSG_WAITALL等待所有消息,告诉内核在没有读到请求的字节数之前不返回

二:具体的实例如下:

服务端:

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <signal.h>

#define PORT 8888
#define SOCKT_IP "127.0.0.1"
#define BACKLOG 2     /*侦听队列长度*/

#define RECV_SEND  0   
#define READV_WRITEV  1

#if RECV_SEND  //recv send
void sig_proccess(int signo)
{
	printf("catch a exit signal %d\n", __LINE__);	
	exit(0);
}

void sig_pipe(int signo)
{
	printf("catch a exit signal %d\n", __LINE__);
	exit(0);
}

void process_conn_server(int s)
{
	ssize_t size = 0;
	char buf[1024] = {0};
	for(;;) {
		size = recv(s, buf, 1024, 0);
		if(size == 0) {				
			return;
		}
		snprintf(buf, 1024, "%d bytes altogether\n", size);
		send(s, buf, strlen(buf)+1, 0);		
	}	
}
#elif READV_WRITEV //readv writev
#include <sys/uio.h>
#include <string.h>
static struct iovec *vs = NULL;
void sig_proccess(int signo)
{
	printf("catch a exit signal %d\n", __LINE__);
	free(vs);	
	exit(0);
}

void sig_pipe(int signo)
{
	printf("catch a exit signal %d\n", __LINE__);
	// free(vs);
	exit(0);
}

void process_conn_server(int s)
{
	ssize_t size = 0;
	char buf[30] = {0};   /*向量缓冲区*/
	
	struct iovec *v=(struct iovec *)malloc(3*sizeof(struct iovec));  /*3个*/
	if(!v) {
		printf("Not enough memory \n");
		return; 
	}
	
	vs = v;  /*每个向量分配10个字节*/
	v[0].iov_base = buf;
	v[1].iov_base = buf + 10;
	v[2].iov_base = buf + 20;
	v[0].iov_len = v[1].iov_len = v[2].iov_len = 10;
	
	for(;;) {
		size = readv(s, v, 3);
		if(size == 0) {				
			return;
		}
		snprintf(v[0].iov_base, 10, "%d ", size);
		snprintf(v[1].iov_base, 10, "bytes alt");
		snprintf(v[2].iov_base, 10, "ogether\n");
		v[0].iov_len = strlen(v[0].iov_base);
		v[1].iov_len = strlen(v[1].iov_base);
		v[2].iov_len = strlen(v[2].iov_base);
		writev(s, v, 3);	
	}	
}

#else  //recvmsg() sendmsg()
#include <sys/uio.h>
#include <string.h>
static struct iovec *vs = NULL;
void sig_proccess(int signo)
{
	printf("catch a exit signal %d\n", __LINE__);
	free(vs);	
	exit(0);
}

void sig_pipe(int signo)
{
	printf("catch a exit signal %d\n", __LINE__);
	free(vs);
	exit(0);
}

void process_conn_server(int s)
{
	//printf("########  ######\n");
	ssize_t size = 0;
	char buf[30] = {0};   /*向量缓冲区*/
	struct msghdr msg;
	memset(&msg, 0, sizeof(struct msghdr));
	
	struct iovec *v=(struct iovec *)malloc(3*sizeof(struct iovec));  /*3个*/
	if(!v) {
		printf("Not enough memory \n");
		return; 
	}
	vs = v;  /*每个向量分配10个字节*/
	
	msg.msg_name = NULL;
	msg.msg_namelen = 0;
	msg.msg_control = NULL;    /*控制域*/
	msg.msg_controllen = 0;
	msg.msg_iov = v;
	msg.msg_iovlen = 30;
	msg.msg_flags = 0;         /*特殊操作flage*/
				
	v[0].iov_base = buf;
	v[1].iov_base = buf + 10;
	v[2].iov_base = buf + 20;
	v[0].iov_len = v[1].iov_len = v[2].iov_len = 10;
	
	for(;;) {
		size = recvmsg(s, &msg, 0);
		if(size == 0) {	
			return;
		}
		printf("get %s \n", v[0].iov_base);
		snprintf(v[0].iov_base, 10, "%d ", size);
		snprintf(v[1].iov_base, 10, "bytes alt");
		snprintf(v[2].iov_base, 10, "ogether\n");
		v[0].iov_len = strlen(v[0].iov_base);
		v[1].iov_len = strlen(v[1].iov_base);
		v[2].iov_len = strlen(v[2].iov_base);
		sendmsg(s, &msg, 0);
	}
}
#endif

int main(int argc, char * argv[])
{
	int ss, sc;
	struct sockaddr_in server_addr, client_addr;   /*服务器地址结构*/
    int err = 0;
	pid_t pid;
	
    signal(SIGINT, sig_proccess);
    signal(SIGPIPE, sig_pipe);

    ss = socket(AF_INET, SOCK_STREAM, 0);
    if(ss < 0) {
    	printf("socket error! \n");
    	return -1;
    }
	
	/*设置服务器*/
	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /*设置为本地地址 0.0.0.0*/
	//inet_pton(AF_INET, SOCKT_IP, &server_addr.sin_addr);
	server_addr.sin_port = htons(PORT);
	
	err = bind(ss, (struct sockaddr*)&server_addr, sizeof(server_addr));
	if (err < 0) {
		printf("bind error! \n");
    	return -1;		
	}
	
	err = listen(ss, BACKLOG);  /*最大监听2个*/
	if (err < 0) {
		printf("listen error! \n");
    	return -1;		
	}
	
	while(1) {
		int addrlen = sizeof(struct sockaddr);
		sc = accept(ss, (struct sockaddr*)&client_addr, &addrlen);
		if(sc < 0)
			continue;
		/*fork子进程处理*/
		pid = fork();
		if( pid == 0 ) {  /*子进程中*/ 
			close(ss);  /*子进程中关闭服务端连接*/
			process_conn_server(sc);
		}else{
			close(sc);	 /*父进程中关闭客户端连接*/
		}
	}
	
	return 0;
}

客户端:

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <signal.h>

static int s;
void sig_proccess_client(int signo)
{
	printf("catch a exit signal \n");
	close(s);
	exit(0);
}

#define PORT 8888

#define RECV_SEND  0
#define READV_WRITEV  1

#if RECV_SEND
void sig_proccess(int signo)
{
	printf("sig_proccess catch a exit signal %d\n", __LINE__);	
	exit(0);
}

void sig_pipe(int signo)
{
	printf("sig_pipe catch a exit signal %d\n", __LINE__);	
	exit(0);
}

void process_conn_client(int s)
{
	ssize_t size = 0;
	char buf[1024] = {0};
	for(;;) {
		size = read(0, buf, 1024);   /*0 标准输入*/
		if(size > 0) {					
			send(s, buf, size, 0);
			size = recv(s, buf, 1024, 0);
			if(size > 0)
				write(1, buf, size); /*1 标准输出*/
		}
	}	
}

#elif READV_WRITEV
#include <sys/uio.h>
#include <string.h>
static struct iovec *vc = NULL;
void sig_proccess(int signo)
{
	printf("sig_proccess catch a exit signal %d \n", __LINE__);
	free(vc);
	exit(0);
}

void sig_pipe(int signo)
{
	printf("sig_pipe catch a exit signal %d\n", __LINE__);
	free(vc);
	exit(0);
}

void process_conn_client(int s)
{
	ssize_t size = 0;
	char buf[30] = {0};   /*向量缓冲区*/
	
	struct iovec *v=(struct iovec *)malloc(3*sizeof(struct iovec));  /*3个*/
	if(!v) {
		printf("Not enough memory \n");
		return; 
	}
	vc = v;  /*每个向量分配10个字节*/
	
	v[0].iov_base = buf;
	v[1].iov_base = buf + 10;
	v[2].iov_base = buf + 20;
	v[0].iov_len = v[1].iov_len = v[2].iov_len = 10;
	
	int i = 0;
	for(;;) {
		size = read(0, v[0].iov_base, 10);   /*0 标准输入*/
		if(size > 0) {
			v[0].iov_len = size;
			writev(s, v, 1);
			v[0].iov_len = v[1].iov_len = v[2].iov_len = 10; 
			size = readv(s, v, 3);
			for(i=0; i<3; i++){
				if(v[i].iov_len > 0)
					write(1, v[i].iov_base, v[i].iov_len); /*1 标准输出*/
			}	
		}
	}	
}

#else  //recvmsg() sendmsg()
#include <sys/uio.h>
#include <string.h>
static struct iovec *vc = NULL;
void sig_proccess(int signo)
{
	printf("sig_proccess catch a exit signal %d \n", __LINE__);
	free(vc);
	exit(0);
}

void sig_pipe(int signo)
{
	printf("sig_pipe catch a exit signal %d\n", __LINE__);
	free(vc);
	exit(0);
}

void process_conn_client(int s)
{
	ssize_t size = 0;
	char buf[30] = {0};   /*向量缓冲区*/
	struct msghdr msg;
	memset(&msg, 0, sizeof(struct msghdr));
	
	struct iovec *v=(struct iovec *)malloc(3*sizeof(struct iovec));  /*3个*/
	if(!v) {
		printf("Not enough memory \n");
		return; 
	}
	vc = v;  /*每个向量分配10个字节*/
	msg.msg_name = NULL;
	msg.msg_namelen = 0;
	msg.msg_control = NULL;    /*控制域*/
	msg.msg_controllen = 0;
	msg.msg_iov = v;
	msg.msg_iovlen = 30;
	msg.msg_flags = 0;         /*特殊操作flage*/
	
	v[0].iov_base = buf;
	v[1].iov_base = buf + 10;
	v[2].iov_base = buf + 20;
	v[0].iov_len = v[1].iov_len = v[2].iov_len = 10;
	
	int i = 0;
	for(;;) {
		size = read(0, v[0].iov_base, 10);   /*0 标准输入*/
		if(size > 0) {
			printf("get %s \n", v[0].iov_base);
			v[0].iov_len = size;
			sendmsg(s, &msg, 0);
			v[0].iov_len = v[1].iov_len = v[2].iov_len = 10; 
			size = recvmsg(s, &msg, 0);
			for(i=0; i<3; i++){
				if(v[i].iov_len > 0)
					write(1, v[i].iov_base, v[i].iov_len); /*1 标准输出*/
			}	
		}
	}	
}	

#endif

int main(int argc, char * argv[])
{
	struct sockaddr_in server_addr;   /*服务器地址结构*/
    int err = 0;
    if(argc == 1) {
    	printf("please input server addr! \n");
    	return 0;
    }

    signal(SIGINT, sig_proccess);
    signal(SIGPIPE, sig_pipe);

    s = socket(AF_INET, SOCK_STREAM, 0);
    if(s < 0) {
    	printf("socket error! \n");
    	return -1;
    }
    
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /*设置为本地任意地址*/
    server_addr.sin_port = htons(PORT);
    
    inet_pton(AF_INET, argv[1], &server_addr.sin_addr);
    connect(s, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));

    process_conn_client(s);
 
    close(s);
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值