系统与网络编程-(项目前准备)
2016-12-13 本文已影响74人
I踏雪寻梅
系统与网络编程
select函数
- select和pselect多用于I/O操作,他们见识多个文件描述符的集合,判断是否有符合条件的时间发生
- I/O操作:不是对 外围设备直接进行操作,而是对设备与cpu连接的接口电路的操作。
- 函数声明: int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
- numfd:一个整形变量的比(readfds,writefds,exceptfds)中的文件描述符的最大值大1.所以必须计算文件描述符最大值以传入。
- readfds:这个文件描述符集合用来见识文件描述符集里每个文件是否有文件可读,当select返回时,将清空不可读内容。
- writefds:这个文件描述符集合用来见识文件描述符集里每个文件是否有文件可写,当select返回时,将清空不可写内容。
-exceptfds:这个文件描述符集合监视文件描述符集中的每个文件是否发生错误
- fd_sets
//将一个文件描述符清零
void FD_CLR(int fd, fd_set *set);
//将文件描述符fd加入到集合set中
int FD_ISSET(int fd, fd_set *set);
void FD_SET(int fd, fd_set *set);
void FD_ZERO(fd_set *set);
- 函数试用
#include <sys/time.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/select.h>
void setMaxFd(int *pMaxFd,int fd)
{
if(*pMaxFd<fd)
{
*pMaxFd=fd;
}
}
int main()
{
int iMaxFd=0;
fd_set readSet;
int ret=0;
#if 0
FD_ZERO(&readSet);//清空
FD_SET(STDIN_FILENO,&readSet);//将SRDIN_FILENO写入集合readSet中
//判断文件描述符集合中是否包含了某个文件描述符
//若包含了返回1,不包含返回0
int ret=FD_ISSET(TDIN_FILENO,&readSet);
printf("ret=%d\n",ret);
#endif
// ret=FD_ISSET(STDOUT_FILENO,&readSet);
// printf("ret=%d\n",ret);
char caBuf[32]={'\0'};
while(1)
{ //select()将会阻塞,直到指定的文件描述符集合中有文件符合相应的I/O操作
FD_ZERO(&readSet);
FD_SET(STDIN_FILENO,&readSet);//将SRDIN_FILENO写入集合readSet中
setMaxFd(&iMaxFd,STDIN_FILENO);
ret=select(iMaxFd+1,&readSet,NULL,NULL,NULL);
if(ret==-1)
{
perror("select");
return -1;
}
//若函数成功返回,那么文件描述符集合中只会包含将要进行IO操作的文件描述符
//其他没有要进行I/O操作的文件描述符会被清空.
//如果需要重新监控,需要将清除掉的问津描述符重新添加到集合中.
//推荐做法:将集合清空,将所有需要监控的文件描述符都添加一遍
if(FD_ISSET((STDIN_FILENO),&readSet))
{
memset(caBuf,'\0',sizeof(caBuf));
read(STDIN_FILENO,caBuf,sizeof(caBuf));
printf("%s\n",caBuf);
}
}
printf("Hello World\n");
return 0;
}
Paste_Image.png
- 地址Address already in use 解决方法:
- UDP试用
- server端
#include<sys/types.h> #include<sys/socket.h> #include <sys/wait.h> #include<stdio.h> #include <stdlib.h> #include <errno.h> #include <netdb.h> #include<string.h> #include<netinet/in.h>//struct sockaddr_in #define MYPORT 5000 int main(int argc,char *argv[]) { int sockfd=-1; struct sockaddr_in clientAddr;//用来存储服务器端套接字地址 struct hostent *he; int numbytes; if(argc!=3) { /*检测是否有所需参数,如没有,则使用显示方法后退出*/ fprintf(stderr,"usage:talker hostname message\n"); return 1; } if((he=gethostbyname(argv[1]))==NULL) { /*取得主机信息,如果显示失败则显示错误信息后退出*/ herror("gethostbyname"); return 1; } sockfd=socket(AF_INET,SOCK_STREAM,0);//使用IPv4基于链接的通信 if(sockfd==-1) { perror("socket"); return -1; } //用结构体来保存服务器的端口和IP地址 clientAddr.sin_family=AF_INET;//使用IPv4(Internet地址族)主机字节顺序 clientAddr.sin_port=htons(MYPORT);//端口号(窗口)将主机字节顺序转换为网络字节顺序 clientAddr.sin_addr=*((struct in_addr*)he->h_addr); bzero(&(clientAddr.sin_zero),8);//添0将整个结构剩余部分数据设为0 int ret; if((numbytes=sendto(sockfd,argv[2],strlen(argv[2]),0, (struct sockaddr *)&clientAddr,sizeof(struct sockaddr)))==-1) { /*将信息发送到指定的主机指定端口,如出错则退出*/ perror("recvfrom"); return -1; } printf("send %d bytes to %s\n",numbytes, inet_ntoa(clientAddr.sin_addr)); /*关闭套接字描述符退出*/ close(sockfd); return 0; }
- client端
#include<sys/types.h> #include <sys/wait.h> #include<sys/socket.h> #include<stdlib.h> #include<stdio.h> #include<string.h> #include <errno.h> #include<netinet/in.h>//struct sockaddr_in #define MYPORT 5000 #define MAXBUFLEN 100 int main(void) { int sockfd = -1; struct sockaddr_in serverAddr; //本机的地址信息 struct sockaddr_in clientAddr; //连接的客户地址信息 int addr_len,numbytes; char buf[MAXBUFLEN]; //创建socket描述符,用于监听接受客户端的连接 //AF_INET:ipv4 //SOCK_STREAM:tcp协议 sockfd = socket(AF_INET, SOCK_DGRAM, 0); //取得一套接字描述符 if (-1 == sockfd) { perror("socket"); //失败则给出失败信息 return -1; } serverAddr.sin_family = AF_INET; //主机字节顺序 serverAddr.sin_port = htons(8888); //网络字节顺序 serverAddr.sin_addr.s_addr = inet_addr("192.168.16.95");//自动设置为自己的ip bzero(&(serverAddr.sin_zero), 8); //将剩余空间清零 //将sockfd端口和地址进行绑定 int ret = -1; ret = bind(sockfd, (struct sockaddr *)&serverAddr , sizeof(serverAddr)); if (-1 == ret) { perror("bind"); return -1; } addr_len=sizeof(struct sockaddr); /*接收数据*/ numbytes=recvfrom(sockfd,buf,MAXBUFLEN,0,(struct sockaddr *)&serverAddr,&addr_len); if(numbytes==-1) { perror("recvfrom"); return -1; } /*显示接受到的数据*/ printf("got packet from%s\n",inet_ntoa(serverAddr.sin_addr)); printf("packet is %d bytes long\n",numbytes); buf[numbytes]='\0'; printf("packet contains %s\n",buf); /*关闭套接字连接*/ close(sockfd); return 0; }
- 简单的文件传输
- client
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define MAXLINE 1024 void usage(char *command) { printf("usage :%s ipaddr portnum filename\n", command); exit(0); } int main(int argc,char **argv) { struct sockaddr_in serv_addr; char buf[MAXLINE]; int sock_id; int read_len; int send_len; FILE *fp; int i_ret; if (argc != 4) { usage(argv[0]); } /* open the file to be transported commented by guoqingbo*/ if ((fp = fopen(argv[3],"r")) == NULL) { perror("Open file failed\n"); exit(0); } /* create the socket commented by guoqingbo*/ if ((sock_id = socket(AF_INET,SOCK_STREAM,0)) < 0) { perror("Create socket failed\n"); exit(0); } memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(atoi(argv[2])); inet_pton(AF_INET, argv[1], &serv_addr.sin_addr); /* connect the server commented by guoqingbo*/ i_ret = connect(sock_id, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)); if (-1 == i_ret) { printf("Connect socket failed\n"); printf("======\n"); return -1; } /* transported the file commented by guoqingbo*/ bzero(buf, MAXLINE); while ((read_len = fread(buf, sizeof(char), MAXLINE, fp)) >0 ) { send_len = send(sock_id, buf, read_len, 0); if ( send_len < 0 ) { perror("Send file failed\n"); exit(0); } bzero(buf, MAXLINE); } fclose(fp); close(sock_id); printf("Send Finish\n"); return 0; }
- server端
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define MAXLINE 1024 void usage(char *command) { printf("usage :%s portnum filename\n", command); exit(0); } int main(int argc,char **argv) { struct sockaddr_in serv_addr; struct sockaddr_in clie_addr; char buf[MAXLINE]; int sock_id; int link_id; int recv_len; int write_leng; int clie_addr_len; FILE *fp; if (argc != 3) { usage(argv[0]); } if ((fp = fopen(argv[2], "w")) == NULL) { perror("Open file failed\n"); exit(0); } if ((sock_id = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("Create socket failed\n"); exit(0); } /*fill the server sockaddr_in struct commented by guoqingbo*/ memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(atoi(argv[1])); serv_addr.sin_addr.s_addr = inet_addr("192.168.16.95"); if (bind(sock_id, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0 ) { perror("Bind socket failed\n"); exit(0); } if (-1 == listen(sock_id, 10)) { perror("Listen socket failed\n"); exit(0); } /* server part commented by guoqingbo*/ while (1) { clie_addr_len = sizeof(clie_addr); link_id = accept(sock_id, (struct sockaddr *)&clie_addr, &clie_addr_len); if (-1 == link_id) { perror("Accept socket failed\n"); exit(0); } bzero(buf, MAXLINE); while (recv_len = recv(link_id, buf, MAXLINE, 0)) { /* receiver data part commented by guoqingbo*/ if(recv_len < 0) { printf("Recieve Data From Server Failed!\n"); break; } printf("#"); write_leng = fwrite(buf, sizeof(char), recv_len, fp); if (write_leng < recv_len) { printf("Write file failed\n"); break; } bzero(buf,MAXLINE); } printf("\nFinish Recieve\n"); fclose(fp); close(link_id); } close(sock_id); return 0; }