非阻塞应用示例
发送端代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<math.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/mman.h>
#include<time.h>
#include<dirent.h>
#include<sys/errno.h>
#include<sys/wait.h>
#include<signal.h>
#include<sys/param.h>
#include<sys/syslog.h>
#include<limits.h>
#include<sys/time.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/sem.h>
#include<errno.h>
#include<sys/shm.h>
#include<pthread.h>
#include<sys/syscall.h>
#include<semaphore.h>
#include<bits/pthreadtypes.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<sys/socket.h>
#define BUFSIZE 128
int main(int argc,char *argv[])
{
int server_sockfd,client_sockfd;
int server_len,client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
int i,byte;
char char_send[BUFSIZE];
server_sockfd=socket(AF_INET,SOCK_STREAM,0); //创建soclet对象
server_address.sin_family=AF_INET;
if(inet_aton(argv[1],(struct in_addr *)&server_address.sin_addr.s_addr)==0) //从argv[1]中提取ip地址且转换为32ip地址
{
perror(argv[1]);
exit(EXIT_FAILURE);
}
server_address.sin_port=htons(7838); //使用特定端口7838
server_len=sizeof(server_address);
bind(server_sockfd,(struct sockaddr *)&server_address,server_len); //绑定IP地址
listen(server_sockfd,5); //监听网络
printf("server wait for connect\n");
client_len=sizeof(client_address);
client_sockfd=accept(server_sockfd,(struct sockaddr *)&client_address,(socklen_t *)&client_len); //等待连接
for(i=0;i<5;i++)
{
memset(char_send,'\0',BUFSIZE);
printf("input message to send:");
fgets(char_send,BUFSIZE,stdin); //首先阻塞在终端接收用户输入
if(byte=send(client_sockfd,char_send,strlen(char_send),0)==-1)
{
perror("send");
exit(EXIT_FAILURE);
}
memset(char_send,'\0',BUFSIZE);
byte=recv(client_sockfd,char_send,BUFSIZE,MSG_DONTWAIT); //非阻塞接收
if(byte>0)
{
printf("get %d message:%s",byte,char_send);
byte=0;
}
else if(byte<0)
{
if(errno==EAGAIN) //如果是因无数据返回的错误,则继续
{
errno=0;
continue;
}
else
{
perror("recv");
exit(EXIT_FAILURE);
}
}
}
shutdown(client_sockfd,2); //关闭socket对象
shutdown(server_sockfd,2);
return 0;
}
发送端:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<math.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/mman.h>
#include<time.h>
#include<dirent.h>
#include<sys/errno.h>
#include<sys/wait.h>
#include<signal.h>
#include<sys/param.h>
#include<sys/syslog.h>
#include<limits.h>
#include<sys/time.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/sem.h>
#include<errno.h>
#include<sys/shm.h>
#include<pthread.h>
#include<sys/syscall.h>
#include<semaphore.h>
#include<bits/pthreadtypes.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<sys/socket.h>
#define MAXBUF 128
int main(int argc,char *argv[])
{
int sockfd,ret,i;
struct sockaddr_in dest,mine;
char buffer[MAXBUF+1];
if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0) //创建socket对象
{
perror("Socket");
exit(EXIT_FAILURE);
}
bzero(&dest,sizeof(dest));
dest.sin_family=AF_INET;
dest.sin_port=htons(7838); // 服务器特定端口,与服务器设置一致
if(inet_aton(argv[1],(struct in_addr *)&dest.sin_addr.s_addr)==0)
{
perror("Socket");
exit(EXIT_FAILURE);
}
bzero(&mine,sizeof(mine));
mine.sin_family=AF_INET;
mine.sin_port=htons(7839); //本地端口
if(inet_aton(argv[2],(struct in_addr *)&mine.sin_addr.s_addr)==0)
{
perror(argv[2]);
exit(EXIT_FAILURE);
}
if(bind(sockfd,(struct sockaddr*)&mine,sizeof(struct sockaddr))==-1) // 绑定自己的ip信息
{
perror(argv[3]);
exit(EXIT_FAILURE);
}
if(connect(sockfd,(struct sockaddr *)&dest,sizeof(dest))!=0)
{
perror("Connect ");
exit(EXIT_FAILURE);
}
if(fcntl(sockfd,F_SETFL,O_NONBLOCK)==-1) //设置为非阻塞
{
perror("fcntl");
exit(EXIT_FAILURE);
}
while(1)
{
bzero(buffer,MAXBUF+1);
ret=recv(sockfd,buffer,MAXBUF,0); //因设置为非阻塞,故此操作非阻塞
if(ret>0)
{
printf("get %d message:%s",ret,buffer);
ret=0;
}
else if(ret<0)
{
if(errno==EAGAIN)
{
errno=0;
continue;
}
else
{
perror("recv");
exit(EXIT_FAILURE);
}
}
memset(buffer,'\0',MAXBUF+1);
printf("input message to send:");
fgets(buffer,MAXBUF,stdin); //在接接收到数据后阻塞在终端,向对方发送数据
if((ret=send(sockfd,buffer,strlen(buffer),0))==-1)
{
perror("send");
exit(EXIT_FAILURE);
}
}
close(sockfd); //关闭socket对象
return 0;
}
》》在接收信息时是非阻塞,但是阻塞了终端,在终端无法打印信息,但却在接受信息,具体实现效果如下
发送端:在连续输入hello test go read why 后 接收端:只打印了hello,后面的所有数据都被终端阻塞,等待用户输入一个字符,之后为:
接收到所有数据并打印出来,这说明只是终端被阻塞,并没有阻塞socket对象接收信息。两端口通信成功。都是基于本地IP地址进行同信。