关闭

tcp socket and i/o

295人阅读 评论(0) 收藏 举报
<pre name="code" class="cpp">1.socket API
#include<netinet/in.h>
	主机字节 => 网络字节
	unsigned short int htons(unsigned short int hostshrot);
	网络字节 => 主机字节
	unsigned short int ntohs(unsigned short int netshrot);
	
	//tcp/ip 协议簇专用socket结构体
	struct sockaddr_in{
		sa_family_t		sin_family; 地址簇 AF_INET
		u_int16_t		sin_port;	 端口号
		struct	in_addr  sin_addr;   IPv4地址结构体;u_int32_ts_addr
	}
	
	//字符串IP -> 整数IP 转换
	#include <arpa/inet.h>
	int	inet_pton(int af,const char* src,void *dst);
	const char* inet_ntop(int af,const void* dst,socklen_t cnt);

2.create socket
	#include <sys/types>
	#include <sys/socket.h>
	/****
	domain:底层协议簇类型
	types :服务类型
	protocol:具体协议
	****/
	int socket (int domain,int type , int protocol);

	命名socket(socket 与 socket地址绑定成为命名)
	bind 成功返回0,否则返回-1,
	#include <sys/types>
	#include <sys/socket.h>
	int bind(int sockfd,const struct sockeaddr *addr,socketlen_t addrlen);
	
3.listening socket
	#include <sys/socket.h>
	int listen(int sockfd,int backlog);

4.receive connect
	
	#include <sys/types.h>
	#include <sys/socket.h>
	int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen);

5.launch connect
	
	#include <sys/types.h>
	#include <sys/socket.h>
	int connect(int sockfd,const struct sockaddr * serv_addr,socklen_t addrlen)
	
	成功:0 失败:-1 ERR:ETIMEOUT:超时 ECONNEFUSED:目标端口不存在
	


6.close connect
	
	#include <sys/socket.h>
	#include <unistd.h>
	
	int close(int fd);
	int shutdown(int sockfd,int howto);
	
	#shutdown 函数中的howto参数
		SHUT_RE : 关闭读这一半
		SHUT_WR	: 关闭写这一半
		SHUT_RDWR: 同时关闭读写

7.data i/o R&W
	TCP 数据读写 API
	#include <sys/socket.h>
	#include <sys/types.h>
	ssize_t recv(int sockfd,void *buf,size_t len,int flags);
	ssize_t send(int sockfd,cons void *buf,size_t len,int flags);
	#UDP 数据读取 API
	ssize_t recvfrom(int sockfd,void *buf,size_t len, int flags,struct sockaddr *src_addr,socklen_t *addrlen);
	ssize_t sendto(int sockfd,cons void *buf,size_t len,int flags,const struct sockaddr * dest_addr,socklen_t addrlen);
		
		recv()flags:参数选项
			MSG_DONTWAIT	非阻塞操作,立即返回结果,不等待
			MSG_ERRQUEUE	错误消息从套接字错误队列接收
			MSG_OOB			接收带外数据	
			MSG_PEEK		查看数据,不进行数据缓冲区清空
			MSG_TRUNC		返回所有数据
			MSG_WAITALL		等待所有消息
		recv()返回的错误码
			EAGIN		套接字定义为非阻塞,操作采用的阻塞方式
			EBADF		参数s 不是合法描述符
			EINTR		接收到中断信号
			EINVAL		传递了不合法参数
			EFAULT		接收缓冲区指针在此进程之外
			ECONNREFUSED	远程主机不允许此操作
		sned()错误码
			EACCES		套接字不可写
			EPIPE		套接字关了
			ENOTCONN	套接字s 表示流式套接字,套接字没有连接
			ENOMEM		无足够内存
			ECONNRESET	连接断开

	readv(int fd,struct iovec *vector,int count);
	writev(int fd,const struct iovec *vector,int count);
		//iovec 结构体
		struct iovec{
			void 	*iov_base;	//缓冲区开始地址
			size_t	iov_len;	//缓冲区长度
		}
	recvmsg(int fd,struct msghdr *msg,int flags);
	sendmsg(int fd,struct msghdr *msg,int flags);
		
I/O 函数/模型	pipe:管道 pair:一对一 splice:拼接
	阻塞,
		输出操作:read(),readv(),recv(),recvfrom()
		输出操作:write(),writev(),send(),sendto()
		接收连接中的:accept()
		发起连接中的:connect()
	非阻塞,
	i/o复用,
	异步i/o
	信号驱动式i/o,
	
	
		pipe(int fd[2]);	
			创建管道进程间通信(fd[0],fd[1]分别构成管道的两端)
			fd[0]读取,fd[1]写入,默认是阻塞
		socketpair(int domain,int type,int protocol,int fd[2]);
			创建双向管道函数方式。进程间通讯
		mmap(void *start, length,int prot,int flags,int fd,off_t offset);
			创建共享内存函数方式。进程间通讯
			port:定义内存的访问权限
				PROT_READ 
				PROT_WRITE
				PROT_EXEC
				PROT_NONE	内存段拒绝访问
			flags:
				MAP_SHARED		进程间共享这段内存
				MAP_PRIVATE		内存段为调用进程私有
				MAP_ANONYMOUS	这段内存不是从文件映射而来
				MAP_FIXD		内存段必须位于start参数指定的地址处
				MAP_HUGETLB		按照大内存界面来分配内存空间
		int munmap(void *start,size_t length); 释放内存空间呢
		
		fcntl(int fd,int cmd,...)	
			修改描述符属性
			cmd:
				F_GETFL 获取fd状态标志
				F_SETFL	设置fd状态标志
			/*文件描述符设置为非阻塞*/
				int setnonblocking(int fd){
					int old_option = fcntl(fd,F_GETFL);
					int new)potion = old_option | O_NONBLOCK;
					fcntl(fd,F_SETFL,new_option);
					return new_option;
				}
		splice()
			两个文件描述符之间移动数据作用\
			ssize_t splice(
				int fd_in,
				loff_t *off_in,
				int fd_out,
				loff_t *off_out,
				size_t len,
				unsigned int flags,
			)
		
		
		
		


</pre><pre name="code" class="cpp">//------------------------	service 端	
/**TCP
1.socket()创建套接字-绑定端口 
2.bind()让套接字处于监听状态-等待连接
3.listen()
4.accept() 一直阻塞 等待客户端连接
5.recv()
6.send()
7.关闭连接 close(recv),close(sock)
*/		
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

int main(int argc,char *argv[]){
		if(argc <=2){
			printf("please input ip address and port number \r \n");
			return -1;
		}
        const char *ip = argv[1];
        int port = atoi(argv[2]);

        struct sockaddr_in address;
        bzero(&address,sizeof(address));

        address.sin_family = AF_INET;

        inet_pton(AF_INET,ip,&address.sin_addr);
        address.sin_port = htons(port);

		int sock = socket(AF_INET,SOCK_STREAM,0);
		if(sock <0){
			printf("socket create failed !");
			return -1;
		}
		int ret = bind(sock,(struct sockeaddr*)&address,sizeof(address));
		if(ret == -1){
			printf("bind failed !");
			return -1;
		}
		ret = listen(sock,5);
		if(ret == -1){
			printf("listen failed !");
			return -1;
		}
		struct sockaddr_in client;
		socklen_t client_addrlength = sizeof(client);
		int connfd = accept(sock,(struct sockaddr*)&client,&client_addrlength);
		if(connfd < 0){
			printf("accept failed !");
		}else{
			char data[64]="i am from JKXY";
			char buffer[64];
			int i,len;
			for(i=0;i<10;i++){
				memset(buffer,0x00,sizeof(buffer));
				len = recv(connfd,buffer,sizeof(buffer),0);
				printf("index is %d len is %d : %s x`\r\n",i,len,buffer);
				sleep(1);
				send(connfd,data,strlen(data),0);
			}
			close(connfd);
		}
		close(sock);
		return 0;
				
}		
//------------------------	
/**TCP
1.socket()	创建套接字
2.connect() 发起连接
3.send()	数据请求(发送)
4.recv()	数据应答
5.close()
*/	
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

int main(int argc,char *argv[]){

        if(argc <=2){
                printf("please input ip address and port number \r \n");
                return -1;
        }

        const char *ip = argv[1];
        int port = atoi(argv[2]);

        struct sockaddr_in server_address;
        bzero(&server_address,sizeof(server_address));

        server_address.sin_family = AF_INET;

        inet_pton(AF_INET,ip,&server_address.sin_addr);
        server_address.sin_port = htons(port);


        int sockfd = socket(AF_INET,SOCK_STREAM,0);

        if(sockfd <0){
                printf("socket create failed !");
                return -1;
        }

        if(connect(sockfd,(struct sockaddr*)&server_address,sizeof(server_address))<0){
                printf("connect failed !");
                return -1;
        }else{
                char data[64]="where are you from ?";
                char buffer[64];
                int i,len;
                for(i=0;i<10;i++){
                        memset(buffer,0x00,sizeof(buffer));
                        send(sockfd,data,strlen(data),0);
                        len = recv(sockfd,buffer,sizeof(buffer),0);
                        sleep(1);
                        printf("index is %d len is %d : %s \r\n",i,len,buffer);
                }
        }

        close(sockfd);
        return 0;

}
//------------------------
UDP -service
1.socket()
2.bind()
3.recvfrom() 阻塞等待接收数据
4.sendto()	 发送

//-----------------------
UDP -client
1.socket()
2.sendto() 数据请求
3.recvfrom() 数据应答
4.close()

//-----------------------i/o

<pre name="code" class="cpp">#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>

int main(){
	int fd[2];
	//创建双向管道函数方式。进程间通讯
	int ret = socketpair(AF_UNIX,SOCK_STREAM,0,fd);
	if(ret < 0){
		perror("socketpair() is error! \r\n");
		exit(1);
	}
	/*fork()创建进程函数  返回值有两个
	 * 大于0时表示创建的是父进程
	 * 等于0表示创建的是子进程
	 * */	
	if(fork()){
		printf("parent process !\r\n");
		int val = 0;
		close(fd[1]);
		while(1){
			sleep(1);
			++val;
			printf("send val to chile:%d \r\n",val);
			write(fd[0],&val,sizeof(val));
			
			//验证套接字写入的值
			read(fd[0],&val,sizeof(val));
			printf("read val from child: %d \r\n",val);
		}
		
	}else{
		/* 父进程关闭了fd[1],
		 * 子进程关闭了fd[0],构成了通道
		 * 首先读出一个值,再通过fd[1]发送给父进程
		 * 
		 **/
		printf("child process \r\n");
		int val;
		close(fd[0]);
		while(1){
			read(fd[1],&val,sizeof(val));
			++val;
			write(fd[1],&val,sizeof(val));
			printf("child process done.\r\n");
		}
		
	}
}




0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:82220次
    • 积分:1620
    • 等级:
    • 排名:千里之外
    • 原创:70篇
    • 转载:82篇
    • 译文:0篇
    • 评论:2条
    文章分类
    最新评论