tcp socket and i/o
1.socket API#include主机字节 => 网络字节unsigned short int htons(unsigned short int hostshrot);网络字节 => 主机字节unsigned short int ntohs(unsigned short int netshrot);//tcp/ip 协议簇专用socket结构体struct so
·
<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");
}
}
}
更多推荐
已为社区贡献8条内容
所有评论(0)