一、基于TCP的网络编程(续day12)
二、并发服务器
三、基于UDP的网络编程
三、基于UDP的网络编程
1、基于UDP网络编程基础
(1)报头格式
头部为8个字节
(2)编程模型
或者
(3)相关函数
sendto(2)
#include<sys/types.h>
#include<sys/socket.h>
int sendto (int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
功能:
在socket上发送一个消息
参数:
sockfd:socket(2)的返回值
buf:指定了消息的存放地址
len:指定发送消息的长度
flags:一般为0
dest_addr:目标地址
addrlen:目标地址长度
返回值:
成功:发送的字节数
错误:-1,errno被设置
recvfrom(2)
#include<sys/types.h>
#include<sys/socket.h>
ssize_t recvfrom(int sockfd,void *buf,size_t len,int flags,struct sockaddr *src_addr,socklen_t *addrlen);
功能:
从socket接收消息
参数:
sockfd:socket(2)的返回值
buf:指定接收消息的空间
len:接收消息的长度
flags:一般为0
src_addr:保存发送方的地址,如果被指定为NULL,那么addrlen也被是空
addrlen:值-结果参数,src_addr地址空间的长度
返回值:
成功:接收到的字节数
错误:-1
发送方正常关闭:0
2、基于UDP的客户端编程
(1)创建通讯描述符
socket(AF_INET,SOCK_DGRAM,0);
(2)使用通讯描述符向服务器发送数据
sendto(2)
(3)等待服务器响应
recvfrom(2)
(4)关闭通讯描述符
close(s_fd);
3、基于UDP的服务器编程
(1)创建通讯描述符
socket(AF_INET,SOCK_DGRAM,0);
(2)将通讯描述符和服务器的地址空间绑定
bind(s_fd,(struct sockaddr *)&server,sizeof(server));
(3)recvfrom等待客户端数据的到来
recvfrom(2)
(4)处理客户端数据
(5)回应客户端消息
...
服务器代码
1 #include<stdio.h> 2 #include<sys/socket.h> 3 #include<syspes.h> 4 #include<netinet/in.h> 5 #include<unistd.h> 6 #include<arpa/inet.h> 7 #include<ctype.h> 8 9 typedef struct sockaddr_in SA4; 10 typedef struct sockaddr SA; 11 int main(void){ 12 int s_fd; 13 //创建通讯描述符 14 SA4 server,client; 15 char buf[128]; 16 s_fd=socket(AF_INET,SOCK_DGRAM,0); 17 if(s_fd==-1){ 18 perror("socket"); 19 return 1; 20 } 21 //初始化server的地址空间 22 server.sin_family=AF_INET; 23 server.sin_port=htons(7776); 24 server.sin_addr.s_addr=htonl(INADDR_ANY); 25 //绑定 26 int b=bind(s_fd,(SA *)&server,sizeof(server)); 27 if(b==-1){ 28 perror("bind"); 29 return 2; 30 } 31 int clilen=sizeof(client);//值结果参数没有必要> 赋值吧 32 //等待客户端的请求到来 33 int r; 34 while((r=recvfrom(s_fd,buf,128,0,(SA *)&client, &clilen))>0){ 35 for(int i=0;i<r;i++){ 36 buf[i]=toupper(buf[i]); 37 38 } 39 sendto(s_fd,buf,r,0,(SA *)&client,sizeof(cl ient)); 40 } 41 42 close(s_fd); 43 return 0; 44 } 客户端代码 1 #include<stdio.h> 2 #include<unistd.h> 3 #include<syspes.h> 4 #include<sys/socket.h> 5 #include<string.h> 6 #include<netinet/in.h> 7 #include<arpa/inet.h> 8 9 typedef struct sockaddr SA; 10 typedef struct sockaddr_in SA4; 11 int main(int argc,char *argv[]){ 12 char buf[]="this is a test! "; 13 char rbuf[128]; 14 //创建通讯描述符 15 int s_fd; 16 SA4 server; 17 server.sin_family=AF_INET; 18 server.sin_port=htons(7776); 19 inet_pton(AF_INET,argv[1],&server.sin_addr); 20 s_fd=socket(AF_INET,SOCK_DGRAM,0); 21 if(s_fd==-1){ 22 perror("socket"); 23 return 1; 24 } 25 //向服务器发送消息 26 sendto(s_fd,buf,strlen(buf+1),0,(SA *)&server,s izeof(server)); 27 //从服务器获取相应消息 28 int r; 29 r=recvfrom(s_fd,rbuf,128,0,NULL,NULL); 30 write(1,rbuf,r); 31 printf(" "); 32 close(s_fd); 33 34 return 0; 35 }
作业:
客户端给服务器发送一个文件名字。服务器收到文件名字之后,在指定的路径之下查找文件是否存在,如果不存在,服务器给客户端发送404,客户端收到404则提示找不到此文件;如果此文件存在,则向客户端发送200,客户端收到200之后,创建这个文件,然后将这个文件的内容下载到客户端中。
1、前言
工作中涉及到文件系统,有时候需要判断文件和目录是否存在。我结合APUE第四章文件和目录,总结一下如何正确判断文件和目录是否存在,方便以后查询。
2、stat系列函数
stat函数用来返回与文件有关的结构信息。stat系列函数有三种情况,分别对应文件名称、文件描述符和符号链接文件。stat结构描述了文件的属性,主要包括文件的类型、文件大小等等。详细stat结构如下所示:
我们可以通过stat获取文件的类型和文件大小等信息。文件类型有:普通文件、目录文件、块特殊文件、字符特殊文件、FIFO、套接字和符号链接。要想通过stat系列函数来判断文件或者目录是否存在,当执行stat函数,如果文件存在时,还需进一步判断该文件是普通文件还是目录文件。
stat系列函数错误返回-1,错误码存在errno中,errno取值如下:
|
1、ENOENT 参数file_name 指定的文件不存在 2、ENOTDIR 路径中的目录存在但却非真正的目录 3、ELOOP 欲打开的文件有过多符号连接问题, 上限为16 符号连接 4、EFAULT 参数buf 为无效指针, 指向无法存在的内存空间 5、EACCESS 存取文件时被拒绝 6、ENOMEM 核心内存不足 7、ENAMETOOLONG 参数file_name 的路径名称太长 |
3、access函数
access函数按照实际用户ID和实际组进行访问权限测试。函数原型为:
#include <unistd.h> int access(const char *pathname, int mode);
mode取值:
F_OK 测试文件是否存在
R_OK 测试读权限
W_OK 测试写权限
X_OK 测试执行权限
正确判断一个文件是否存在是用access函数,实现如下所示:
4、oepndir函数
opendir函数用来打开文件目录,成功返回指针,出错返回NULL。实现如下:
(文件查找部分来自脚本之家)