大型网站建设视频,php网站开发视频教程,商丘市建设,没有网站可以做百度排名吗1. 网络编程概述#xff08;444.1#xff09;
TCP/UDP对比
TCP 面向连接#xff08;如打电话要先拨号建立连接#xff09;#xff1b;UDP 是无连接的#xff0c;即发送数据之前不需要建立连接TCP 提供可靠的服务。也就是说#xff0c;通过 TCP 连接传送的数据#xf…1. 网络编程概述444.1
TCP/UDP对比
TCP 面向连接如打电话要先拨号建立连接UDP 是无连接的即发送数据之前不需要建立连接TCP 提供可靠的服务。也就是说通过 TCP 连接传送的数据无差错不丢失不重复且按序到达UDP 尽最大努力交付即不保证可靠交付TCP 面向字节流实际上是 TCP 把数据看成一连串无结构的字节流UDP 是面向报文的 UDP 没有拥塞控制因此网络出现拥塞不会使源主机的发送速率降低对实时应用很有用如 IP 电话实时视频会议等每一条 TCP 连接只能是点到点的UDP 支持一对一一对多多对一和多对多的交互通信TCP 首部开销 20 字节UDP 的首部开销小只有 8 个字节TCP 的逻辑通信信道是全双工的可靠信道UDP 则是不可靠信道
端口号作用
一台拥有 IP 地址的主机可以提供许多服务比如 Web 服务、FTP 服务、SMTP 服务等这些服务完全可以通过 1 个 IP 地址来实现。那么主机是怎样区分不同的网络服务呢显然不能只靠 IP 地址因为 IP 地址与网络服务的关系是一对多的关系。实际上是通过 “IP 地址 端口号” 来区分不同的服务的。端口提供了一种访问通道服务器一般都是通过知名端口号来识别的。例如对于每个 TCP/IP 实现来说FTP 服务器的 TCP 端口号都是 21每个 Telnet 服务器的 TCP 端口号都是 23每个 TFTP 简单文件传送协议服务器的 UDP 端口号都是 69。 2. 字节序445.2 字节序即字节在电脑中存放时的序列与输入输出时的序列是先到的在前还是后到的在前。字节序是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序。 Little endian将低序字节存储在起始地址Big endian将高序字节存储在起始地址
LE little-endian 小端字节序BE big-endian 大端字节序网络字节序 大端字节序
字节序转换api
#include arpa/inet.huint16_t htons(uint16_t host16bitvalue); //返回网络字节序的值
uint32_t htonl(uint32_t host32bitvalue); //返回网络字节序的值
uint16_t ntohs(uint16_t net16bitvalue); //返回主机字节序的值
uint32_t ntohl(uint32_t net32bitvalue); //返回主机字节序的值h代表host主机n代表nets代表short两个字节l代表long4个字节通过上面的4个函数可以实现主机字节序和网络字节序之间的转换。有时可以用INADDR_ANYINADDR_ANY指定地址让操作系统自己获取
3. socket编程步骤446.3 Sockt服务器和客户端的开发步骤 TCP Server
创建套接字socket为套接字添加信息IP地址和端口号bind监听网络连接listen监听到有客户端接入接受一个连接accept数据交互read、write、read关闭套接字断开连接close
4. Linux提供的API简析447.4
指定讲“汉语”连接协议
int socket(int domain, int type, int protocol);
地址准备好
地址转换API int inet_aton(const char* straddr,struct in_addr *addrp); 把字符串形式的“192.168.1.123”转为网络能识别的格式char* inet_ntoa(struct in_addr inaddr); 把网络格式的ip地址转为字符串形式 监听 连接 数据收发
5.1 数据收发常用第一套API 5.2 数据收发常用第二套API
客户端的connect函数
5. socket服务端代码实现一448.5
man 2 socket、man 2 bind、man htons、man inet_aton
查找某段源码在哪个头文件之下的方法
cd /usr/includelsgrep struct sockaddr_in { * -nir 搜索其在哪个头文件下被定义/声明※ (星号) 在当前目录底下n 找出时显示其所在行号i 不区分大小写r 递归的方式 vi linux/in.h 261 grep struct in_addr { * -nirvi linux/in.h 89
代码相关
SOCKET/server.c
#include stdio.h//printf
#include sys/types.h//socket bind /* See NOTES */
#include sys/socket.h//socket bind
//#include linux/in.h//struct sockaddr_in//和netinet/in.h冲突
#include arpa/inet.h//htons
#include netinet/in.h//inet_aton
#include stdlib.h//exit
//int socket(int domain, int type, int protocol);
//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
/*struct sockaddr_in {//也可在linux/in.h中找到__kernel_sa_family_t sin_family; /* Address family */
//__be16 sin_port; /* Port number */
//struct in_addr sin_addr; /* Internet address *//* Pad to size of struct sockaddr. */
//unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
// sizeof(unsigned short int) - sizeof(struct in_addr)];
//};*/
/*struct in_addr {__be32 s_addr;
};*/
//int listen(int sockfd, int backlog);
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);//fd,客户端地址客户端地址长度地址返回新的建立的socket的通道
int main(int argc, char **argv)
{int s_fd;//1. socket 获取/创建套接字s_fd socket(AF_INET, SOCK_STREAM, 0);//IPv4 因特网域TCP协议自动选择type类型对应的默认协议也可用宏IPPROTO_TCP TCPif(s_fd -1){//判断建立socket通道是否成功perror(socket);//把错误的问题打出来exit(-1);//退出这个程序}//2. bind 绑定struct sockaddr_in s_addr;s_addr.sin_family AF_INET;//协议族跟domain一致s_addr.sin_port htons(8989);//端口号一般3000以下为操作系统来用建议用户5000以上 端口号由主机to网络 返回网络字节序的值inet_aton(192.168.2.13,s_addr.sin_addr);//本机ip地址由字符串形式to网络格式//ifconfigbind(s_fd,(struct sockaddr *)s_addr,sizeof(struct sockaddr_in));//把ip地址端口号和s_fd绑定起来//fd,强转为struct sockaddr型结构体的长度//3. listenlisten(s_fd,10);//监听10个连接不阻塞//4. accept 接受int c_fd accept(s_fd,NULL,NULL);//先不关心客户端是谁//如果没连接到会卡在这//后续的操作用新的c_fd//5. read//6. writeprintf(connected!\n);while(1)//有客户端连上不让其退出return 0;
}ifconfig 本机网络地址和本机回环地址
win10 telnet不是内部或外部命令已解决
telnet 在win10下默认是不开启的所以需要我们自己手动开启。
wins 搜索控制面板点击进入 在控制面板中选择程序——启动或关闭 windows 功能勾选 Telnet 客户端选项确定进行安装。 勾选 “Telnet 客户端” 更改 windows 设置需要一分钟左右的时间不要关闭。安装完成后重启计算机生效。实测可不重启 windows功能的telnet功能已经开启我们测试下是否可以正常使用输入telnetip地址。
6. socket服务端代码实现二449.6
SOCKET/server2.c建立服务器并等待客户端连接 后收发
#include stdio.h//printf
#include sys/types.h//socket bind /* See NOTES */
#include sys/socket.h//socket bind
//#include linux/in.h//struct sockaddr_in//和netinet/in.h冲突
#include arpa/inet.h//htons
#include netinet/in.h//inet_aton
#include stdlib.h//exit
#include string.h//memset
#include unistd.h//read write
//int socket(int domain, int type, int protocol);
//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
/*struct in_addr {__be32 s_addr;
};*/
//int listen(int sockfd, int backlog);
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);//fd,客户端地址客户端地址长度返回新的建立的socket的通道
int main()
{int s_fd;//1. socketint c_fd;//4. acceptint n_read;//5. readchar readBuf[128];//5. read//定义一个数组就不用像指针还要开辟空间char *msg I get your connection\n;//6. writestruct sockaddr_in s_addr;//2. bindstruct sockaddr_in c_addr;//2. bindmemset(s_addr,0,sizeof(struct sockaddr_in));//清空memset(c_addr,0,sizeof(struct sockaddr_in));//清空//1. socket 获取/创建套接字s_fd socket(AF_INET, SOCK_STREAM, 0);//IPv4 因特网域TCP协议自动选择type类型对应的默认协议也可用宏IPPROTO_TCP TCPif(s_fd -1){//判断建立socket通道是否成功perror(socket);//把错误的问题打出来exit(-1);//退出这个程序}//2. bind 绑定s_addr.sin_family AF_INET;//协议族跟domain一致s_addr.sin_port htons(8989);//端口号一般3000以下为操作系统来用建议用户5000以上 端口号由主机to网络 返回网络字节序的值inet_aton(192.168.2.13,s_addr.sin_addr);//本机ip地址由字符串形式to网络格式//ifconfigbind(s_fd,(struct sockaddr *)s_addr,sizeof(struct sockaddr_in));//把ip地址端口号和s_fd绑定起来//3. listenlisten(s_fd,10);//监听10个连接//4. accept 接受int clen sizeof(struct sockaddr_in);c_fd accept(s_fd,(struct sockaddr *)c_addr,clen);//如果没连接到会卡在这if(c_fd -1){perror(accept);}printf(get connected: %s\n,inet_ntoa(c_addr.sin_addr));//连上后打印 “已连接” 和客户端的 ip地址//5. readn_read read(c_fd, readBuf, 128);if(n_read -1){perror(read);}else{printf(get message:%d,%s\n,n_read,readBuf);//打印收到了多少个字节的消息和消息的内容}//6. writewrite(c_fd,msg,strlen(msg));//用提前定义的字符串如直接写入字符串字节大小也随意写如128,会造成乱码因有无用的字节return 0;
}7. socket客户端代码实现450.7
man 2 connectSOCKET/client.c连接服务器后 客户端发收
#include stdio.h
#include sys/types.h /* See NOTES */
#include sys/socket.h
//#include linux/in.h
#include netinet/in.h
#include arpa/inet.h
#include stdlib.h
#include string.h
#include unistd.h//read write
//int socket(int domain, int type, int protocol);
//int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
int main(int argc, char **argv)
{int c_fd;//1. socketint n_read;//4. readchar readBuf[128];//4. readchar *msg Im a msg from Client;//3. write//1. socket 获取/创建套接字c_fd socket(AF_INET, SOCK_STREAM, 0);if(c_fd -1){perror(socket);exit(-1);}//2.connect//连接服务器 struct sockaddr_in c_addr;memset(c_addr,0,sizeof(struct sockaddr_in));c_addr.sin_family AF_INET;c_addr.sin_port htons(8989);inet_aton(192.168.2.13,c_addr.sin_addr);//服务器的ip地址if(connect(c_fd, (struct sockaddr *)c_addr,sizeof(struct sockaddr)) -1){//连接时会阻塞直到出结果为之perror(connect);exit(-1);}//3. write//写write(c_fd,msg,strlen(msg));//4. read//读 n_read read(c_fd, readBuf, 128);if(n_read -1){perror(read);}else{printf(get message from server:%d,%s\n,n_read,readBuf);//打印收到了多少个字节的消息和消息的内容}return 0;
}8. 实现双方聊天451.8 SOCKET/server3.c服务器可以一直接收多个客户端的连接并和某个客户端互发消息
#include stdio.h//printf
#include sys/types.h//socket bind /* See NOTES */
#include sys/socket.h//socket bind
//#include linux/in.h//struct sockaddr_in//冲突
#include arpa/inet.h//htons
#include netinet/in.h//inet_aton
#include stdlib.h//exit
#include string.h//memset
#include unistd.h//read write
//int socket(int domain, int type, int protocol);
//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
/*struct in_addr {__be32 s_addr;
};*/
//int listen(int sockfd, int backlog);
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);//fd,客户端地址客户端地址长度返回新的建立的socket的通道
int main(int argc, char **argv)
{int s_fd;//1. socketint c_fd;//4. acceptint n_read;//5. readchar readBuf[128];//5. read// char *msg I get your connection;char msg[128] {0};//6. writestruct sockaddr_in s_addr;//2. bindstruct sockaddr_in c_addr;//2. bindmemset(s_addr,0,sizeof(struct sockaddr_in));memset(c_addr,0,sizeof(struct sockaddr_in));if(argc ! 3){//如果没有输入参数 会提示printf(param is not good\n);exit(-1);}//1. socket 获取套接字s_fd socket(AF_INET, SOCK_STREAM, 0);//IPv4 因特网域TCP协议自动选择type类型对应的默认协议也可用宏IPPROTO_TCP TCPif(s_fd -1){//判断建立socket通道是否成功perror(socket);//把错误的问题打出来exit(-1);//退出这个程序}//2. bind 绑定s_addr.sin_family AF_INET;//协议族跟domain一致s_addr.sin_port htons(atoi(argv[2]));//字符串转换为整形数inet_aton(argv[1],s_addr.sin_addr);//本机ip地址由字符串形式to网络格式//ifconfigbind(s_fd,(struct sockaddr *)s_addr,sizeof(struct sockaddr_in));//把ip地址端口号和s_fd绑定起来//3. listenlisten(s_fd,10);//监听10个连接//4. accept 接受连接int clen sizeof(struct sockaddr_in);while(1){//不让程序退出 一直循环进行//不要在while(1)里定义变量//同时收和发c_fd accept(s_fd,(struct sockaddr *)c_addr,clen);//如果没连接到会卡在这if(c_fd -1){perror(accept);}printf(get connected: %s\n,inet_ntoa(c_addr.sin_addr));//连上后打印 “已连接” 和客户端的 ip地址if(fork() 0){//在网络服务进程中父进程等待客户端的服务请求 当这种请求到达时父进程调用fork使子进程处理此请求。父进程则继续等待下一个服务请求到达//6. writeif(fork()0){//如果要用两个while(1)要么用多线程要么用fork创建子进程while(1){memset(msg,0,sizeof(msg));printf(input: );//gets(msg);//gets不安全,已经被废弃fgets(msg,sizeof(msg),stdin);//阻塞msg[strcspn(msg, \n)] \0;//移除输入中的换行符write(c_fd,msg,strlen(msg));//6. write} } //5. readwhile(1){memset(readBuf,0,sizeof(readBuf));//每次写之前清空n_read read(c_fd, readBuf, 128);//阻塞if(n_read -1){perror(read);}else{printf(get message from client:%d,%s\n,n_read,readBuf);//打印收到了多少个字节的消息和消息的内容}}}}return 0;
}SOCKET/client2.c多个客户端分别连接服务器并和服务器互发消息
#include stdio.h
#include sys/types.h /* See NOTES */
#include sys/socket.h
//#include linux/in.h
#include netinet/in.h
#include arpa/inet.h
#include stdlib.h
#include string.h
#include unistd.h//read write
//int socket(int domain, int type, int protocol);
//int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
//char *fgets(char *s, int size, FILE *stream);
int main(int argc, char **argv)
{int c_fd;//1. socketint n_read;//4. readchar readBuf[128];//4. read//char *msg Im a msg from Client;//3. write char msg[128] {0};if(argc ! 3){//如果没有输入参数 会提示printf(param is not good\n);exit(-1);}//1. socket 获取/创建套接字c_fd socket(AF_INET, SOCK_STREAM, 0);if(c_fd -1){perror(socket);exit(-1);}//2.connect 连接服务器 struct sockaddr_in c_addr;memset(c_addr,0,sizeof(struct sockaddr_in));c_addr.sin_family AF_INET;c_addr.sin_port htons(atoi(argv[2]));inet_aton(argv[1],c_addr.sin_addr);//服务器的ip地址if(connect(c_fd, (struct sockaddr *)c_addr,sizeof(struct sockaddr)) -1){//连接时阻塞 成功后往下perror(connect);exit(-1);}while(1){//不让程序退出 一直循环进行//同时发和收//3. write 写if(fork()0){//如果要用两个while(1)要么用多线程要么用fork创建子进程while(1){memset(msg,0,sizeof(msg));//每次写之前清空printf(input: );//gets(msg);//gets不安全,已经被废弃fgets(msg,sizeof(msg),stdin);//阻塞msg[strcspn(msg, \n)] \0;//移除输入中的换行符write(c_fd,msg,strlen(msg));}}//4. read 读while(1){memset(readBuf,0,sizeof(readBuf));n_read read(c_fd, readBuf, 128);//阻塞if(n_read -1){perror(read);}else{printf(get message from server:%d,%s\n,n_read,readBuf);//打印收到了多少个字节的消息和消息的内容}}}return 0;
}9. 多方消息收发452.9
上节课的逻辑shell终端获得输入并不知道是哪个子进程的输入所以返回给客户端也并不知道是哪个子进程之间存在资源竞争 SOCKET/server4.c自动主动回复给客户端消息类似心跳包
#include stdio.h//printf
#include sys/types.h//socket bind /* See NOTES */
#include sys/socket.h//socket bind
//#include linux/in.h//struct sockaddr_in//冲突
#include arpa/inet.h//htons
#include netinet/in.h//inet_aton
#include stdlib.h//exit
#include string.h//memset
#include unistd.h//read write
//int socket(int domain, int type, int protocol);
//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
/*struct in_addr {__be32 s_addr;
};*/
//int listen(int sockfd, int backlog);
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);//fd,客户端地址客户端地址长度返回新的建立的socket的通道
int main(int argc, char **argv)
{int s_fd;//1. socketint c_fd;//4. acceptint n_read;//5. readint mark 0;//第几个客户端char readBuf[128];//5. read// char *msg I get your connection;char msg[128] {0};//6. writestruct sockaddr_in s_addr;//2. bindstruct sockaddr_in c_addr;//2. bindmemset(s_addr,0,sizeof(struct sockaddr_in));memset(c_addr,0,sizeof(struct sockaddr_in));if(argc ! 3){//如果没有输入参数 会提示printf(param is not good\n);exit(-1);}//1. socket 获取套接字s_fd socket(AF_INET, SOCK_STREAM, 0);//IPv4 因特网域TCP协议自动选择type类型对应的默认协议也可用宏IPPROTO_TCP TCPif(s_fd -1){//判断建立socket通道是否成功perror(socket);//把错误的问题打出来exit(-1);//退出这个程序}//2. bind 绑定s_addr.sin_family AF_INET;//协议族跟domain一致s_addr.sin_port htons(atoi(argv[2]));//字符串转换为整形数inet_aton(argv[1],s_addr.sin_addr);//本机ip地址由字符串形式to网络格式//ifconfigbind(s_fd,(struct sockaddr *)s_addr,sizeof(struct sockaddr_in));//把ip地址端口号和s_fd绑定起来//3. listenlisten(s_fd,10);//监听10个连接//4. accept 接受连接int clen sizeof(struct sockaddr_in);while(1){//不让程序退出 一直循环进行//不要在while(1)里定义变量//同时收和发c_fd accept(s_fd,(struct sockaddr *)c_addr,clen);//如果没连接到会卡在这if(c_fd -1){perror(accept);}mark;printf(get connected: %s\n,inet_ntoa(c_addr.sin_addr));//连上后打印 “已连接” 和客户端的 ip地址if(fork() 0){//在网络服务进程中父进程等待客户端的服务请求 当这种请求到达时父进程调用fork使子进程处理此请求。父进程则继续等待下一个服务请求到达//一有客户端接入就调用子进程//6. writeif(fork()0){//如果要用两个while(1)要么用多线程要么用fork创建子进程while(1){sprintf(msg,welcome NO.%d Client,mark);//每个客户端都能知道其连接有无丢失write(c_fd,msg,strlen(msg));//6. write//对于服务端都能收到客户端的请求sleep(3);//类似心跳包每隔3s发一串话} } //5. readwhile(1){//接收每一个客户端发来的消息memset(readBuf,0,sizeof(readBuf));//每次写之前清空n_read read(c_fd, readBuf, 128);//阻塞if(n_read -1){perror(read);}else{printf(get message from NO.%d Client :%d,%s\n,mark,n_read,readBuf);//打印收到了多少个字节的消息和消息的内容}}}}return 0;
}10. 项目运行结果453.1 11. 项目研发思路454.2
客户端要实现的指令
get a.c获取服务器的文件 a.cput a.c上传文件 a.c 到服务器cd a进入服务器某文件夹 als展示服务器有哪些文件和文件夹pwd显示当前文件夹所在路径lcd aa进入客户端本地的某文件夹 aalls展示客户端本地有哪些文件和文件夹quit退出连接
服务端去解析这些指令执行这些指令返回这些指令的结果
自行搜索 “Linux 判断文件是否存在” 的函数写 demo 测试再整合进项目中 recv 和 read 区别 recv 第四个参数 MSG_PEEK 就可以多次读其返回值等0时表示客户端连接断开小于0读数据失败read 只能读一次套接字中的数据就
12. 项目指导455.3
服务端 客户端