文章目录

    • 1.1 信号灯集函数接口
      • 1.semget
      • 2.semctl
      • 3.封装初始化函数
      • 4. semop
  • 二 网络编程
    • 2.1 为什么要学习网络编程
    • 2.2 发展
      • 2.2.1 ARPnet
      • 2.2.2 TCP/IP协议
    • 2.3 网络体系结构以及OSI开放系统互联模型
    • 2.4 TCP/IP协议族
    • 2.5 五层模型
      • 2.6 TCP和UDP的异同点
    • 2.7 函数讲解
      • 2.7.1 socket
      • 2.7.2 bind()
      • 2.7.3 listen
      • 2.7.4 accept
      • 2.7.5 connect
    • 2.8 TCP服务器
    • 2.9 TCP客户端
    • 2.10 TCP并发服务器
    • 2.11 UDP 网络编程
      • 函数接口recvfrom/sendto

一 IPC通信之 信号灯集
信号灯集:是在内核空间的信号灯的集合

1.1 信号灯集函数接口

1.semget

头文件:#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>原型:int semget(key_t key, int nsems, int semflg);
功能:创建或者打开一个信号灯集
参数:key:信号灯集的秘钥(和共享内存,消息队列类似)nsems:创建的信号灯集中存在几个信号灯semflg:打开的方式IPC_CREAT:如果共享内存存在,则打开,不存在则创建例如:IPC_CREAT | 0664IPC_EXCL:如果存在则报错返回,如果不存在配合IPC_CREAT创建
返回值:成功返回一个信号灯集的ID失败返回-1

2.semctl

头文件:#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>原型:int semctl(int semid, int semnum, int cmd, ...);
功能:控制信号灯集
参数:semid:要控制的信号灯集的ID号semnum:信号灯的编号cmd:控制方式IPC_RMID:删除信号灯集,不考虑第二个参数GETVAL:获取信号灯的值SETVAL:设置信号灯的值..:可变参数:是一个联合体union semun {int              val;    /* Value for SETVAL */struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */unsigned short  *array;  /* Array for GETALL, SETALL */struct seminfo  *__buf;  /* Buffer for IPC_INFO(Linux-specific) */};
返回值:成功返回 0GETVAL:返回一个信号灯的值失败返回-1

3.封装初始化函数

int sem_init_val(int semid,int semnum,int val)
{union semun myval;  //需要自己定义myval.val = val;if(-1 ==semctl(semid,semnum,SETVAL,myval)){printf("初始化信号灯%d失败\n",semnum);return -1;   }return 0;
}

4. semop

头文件:#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>原型:int semop(int semid, struct sembuf *sops, size_t nsops);
功能:操作方式
参数:
semid:信号灯集的ID号
sops:操作方法结构体的地址unsigned short sem_num;  /* semaphore number */short          sem_op;   /* semaphore operation */short          sem_flg;  /* operation flags */使用案例:struct sembuf sops[2];int semid;/* Code to set semid omitted */sops[0].sem_num = 0;        /* Operate on semaphore 0 */sops[0].sem_op = 0;         /* Wait for value to equal 0 */sops[0].sem_flg = 0;sops[1].sem_num = 0;        /* Operate on semaphore 0 */sops[1].sem_op = 1;         /* Increment value by one */sops[1].sem_flg = 0;if (semop(semid, sops, 2) == -1) {perror("semop");exit(EXIT_FAILURE);}nsops:同时操作的个数如果说同时操作很多信号灯,填写一个结构体数组
返回值:成功返回0失败返回-1

//write

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
union semun {int  val;    /* Value for SETVAL */
};
int sem_init_val(int semid,int semnum,int val)
{union semun myval;  //需要自己定义myval.val = val;if(-1 ==semctl(semid,semnum,SETVAL,myval)){printf("初始化信号灯%d失败\n",semnum);return -1;   }return 0;
}
int sem_p(int semid,int semnum) //参数1:信号灯集  2.信号灯的编号
{   struct sembuf mybuf;mybuf.sem_num = semnum;        /* Operate on semaphore 0 */mybuf.sem_op = -1;         /* Wait for value to equal 0 */mybuf.sem_flg = 0;if(-1 == semop(semid,&mybuf,1)){printf("p操作失败\n");return -1;}return 0;
}
int sem_v(int semid,int semnum) //参数1:信号灯集  2.信号灯的编号
{   struct sembuf mybuf;mybuf.sem_num = semnum;        /* Operate on semaphore 0 */mybuf.sem_op = 1;         /* Wait for value to equal 0 */mybuf.sem_flg = 0;if(-1 == semop(semid,&mybuf,1)){printf("v操作失败\n");return -1;}return 0;
}
int main(int argc, char const *argv[])
{//生成一个共享内存使用的key值key_t mykey1 = ftok("/home/jsetc/jsetc/208/",'a');if(-1 == mykey1){perror("生成键值失败");return -1;}//生成一个自定义key值key_t mykey = ftok("/home/jsetc/jsetc/208/day17/",'a');if(-1 == mykey){perror("ftok");return -1;}//创建信号灯集int semid = semget(mykey,2,IPC_CREAT | 0664);if(-1 == semid){perror("semget");return -1;}//初始化信号灯集sem_init_val(semid,0,1);sem_init_val(semid,1,0);//创建共享内存int shmid = shmget(mykey1,4096,IPC_CREAT | 0664);if(-1 == shmid){perror("shmget");return -1;}printf("创建或者打开共享内存成功\n");//地址映射char *buf = (char *)shmat(shmid,NULL,0);if((char *)-1 == buf){perror("shmat");return -1;}while(1){sem_p(semid,0);    //p操作printf("请输入\n");scanf("%s",buf);sem_v(semid,1);}return 0;
}
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
union semun {int  val;    /* Value for SETVAL */
};
int sem_init_val(int semid,int semnum,int val)
{union semun myval;  //需要自己定义myval.val = val;if(-1 ==semctl(semid,semnum,SETVAL,myval)){printf("初始化信号灯%d失败\n",semnum);return -1;   }return 0;
}
int sem_p(int semid,int semnum) //参数1:信号灯集  2.信号灯的编号
{   struct sembuf mybuf;mybuf.sem_num = semnum;        /* Operate on semaphore 0 */mybuf.sem_op = -1;         /* Wait for value to equal 0 */mybuf.sem_flg = 0;if(-1 == semop(semid,&mybuf,1)){printf("p操作失败\n");return -1;}return 0;
}
int sem_v(int semid,int semnum) //参数1:信号灯集  2.信号灯的编号
{   struct sembuf mybuf;mybuf.sem_num = semnum;        /* Operate on semaphore 0 */mybuf.sem_op = 1;         /* Wait for value to equal 0 */mybuf.sem_flg = 0;if(-1 == semop(semid,&mybuf,1)){printf("v操作失败\n");return -1;}return 0;
}
int main(int argc, char const *argv[])
{//生成一个共享内存使用的key值key_t mykey1 = ftok("/home/jsetc/jsetc/208/",'a');if(-1 == mykey1){perror("生成键值失败");return -1;}//生成一个自定义key值key_t mykey = ftok("/home/jsetc/jsetc/208/day17/",'a');if(-1 == mykey){perror("ftok");return -1;}//创建信号灯集int semid = semget(mykey,2,IPC_CREAT | 0664);if(-1 == semid){perror("semget");return -1;}//初始化信号灯集sem_init_val(semid,0,1);sem_init_val(semid,1,0);//创建共享内存int shmid = shmget(mykey1,4096,IPC_CREAT | 0664);if(-1 == shmid){perror("shmget");return -1;}printf("创建或者打开共享内存成功\n");//地址映射char *buf = (char *)shmat(shmid,NULL,0);if((char *)-1 == buf){perror("shmat");return -1;}while(1){sem_p(semid,1);    //p操作printf("buf = %s\n",buf);sem_v(semid,0);}    return 0;
}

二 网络编程

2.1 为什么要学习网络编程

网络编程就是最后一种进程间通信的方式-----》套接字通信
套接字通信:前六种进程间通信只能实现同一台主机的多个进程通信,但是套接字通信可以实现不同主机的多个进程间通信。

2.2 发展

Arpanet
TCP/IP协议:一共两个协议
网络体系结构:发明了osi开放系统互联模型
TCP/IP协议族:有很多个协议组成

2.2.1 ARPnet

是网络的最早雏形
不能互联不同类型的计算机和不同类型的操作系统,没有纠错功能。

2.2.2 TCP/IP协议

TCP/IP协议分成了两个不同的协议:
用来检测网络传输中差错的传输协议:TCP
专门分则对不同网络进行互联的互联网协议:IP

2.3 网络体系结构以及OSI开放系统互联模型

OSI(国际标准化组织)提供的一个网络体系结构
OSI因为层次结构比较复杂,所以到目前也没有使用,但是他是最早提出的网络体系结构
OSI七层模型:
应用层: 面向用户的,应用程序
表示层:对数据进行加密和解密
会话层:建立逻辑名字和物理名字之间的关系
运输层:用于控制数据的有效传输
网络层:数据分组,路由选择
数据链路层:将数据组成发送或者接收的帧数据
物理层:选择物理介质
注意:每个层次之间的顺序是不能改变的

2.4 TCP/IP协议族

后期基于OSI发明了TCP/IP协议族,这个协议族由很多协议组成:
TCP/IP协议族一共四层:
应用层:telnet,www,FTP,TFTP,SIP
传输层:tcp udp
网络层:IP,ICMP
网络接口与物理层:网卡驱动,物理接口

2.5 五层模型

应用层:
传输层:
网络层:
数据链路层:
物理层:

2.6 TCP和UDP的异同点

相同点:同为传输协议
不同点:TCP是面向连接的,可靠的,基于字节流的传输协议UDP是面向无连接,不可靠的,基于数据报的传输协议
Tcp的概念是一种面向链接的传输协议,它能提供高可靠性的通信(即数据无误,数据不丢失,数据无失序,数据无重复的到达),TCP有回传机制使用情况:适合对于传输质量要求较高,以及传输大量数据的通信,比图MSN/QQ登录,账号管理时需要使用TCP协议
UDP的概念是不可靠的,无连接的传输协议,在数据发送前,因为不需要进行链接,所以可以高效率的数据传输使用情况:适用于对于实时性要求较高的场景,比如:流媒体

2.7 函数讲解

2.7.1 socket

头文件:#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>原型:int socket(int domain, int type, int protocol);
功能:创建套接字,返回一个文件描述符
参数:domain:通信域AF_UNIX, AF_LOCAL   Local communication              unix(7)   //本地通信AF_INET             IPv4 Internet protocols          ip(7)    //ipv4网络协议AF_INET6            IPv6 Internet protocols          ipv6(7)   //ipv6网络协议AF_IPX              IPX - Novell protocolsAF_NETLINK          Kernel user interface device     netlink(7)AF_X25              ITU-T X.25 / ISO-8208 protocol   x25(7)AF_AX25             Amateur radio AX.25 protocolAF_ATMPVC           Access to raw ATM PVCsAF_APPLETALK        AppleTalk                        ddp(7)AF_PACKET           Low level packet interface       packet(7)   //底层协议通信AF_ALG              Interface to kernel crypto APItype:套接字类型SOCK_STREAM   :流式套接字   --->tcp  SOCK_DGRAM   : 数据报套接字 --->udpSOCK_RAW :      原始套接字protocol:附加协议,传0表示不需要其他协议
返回值:成功:文件描述符失败: -1

2.7.2 bind()

头文件:#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>原型:int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
功能:将套接字与网络信息结构体绑定
参数:sockfd:文件描述符,socket的返回值addr:网络信息结构体通用结构体:一般不用struct sockaddr {sa_family_t sa_family;char        sa_data[14];}网络信息结构体:                                 stuct sockaddr_in{sa_family_t sin_family;   //地址族:AF_INETin_port_t  sin_port;    //网络字节序的端口号struct in_addr sin_addr  //ip地址   ---》struct in_addr{uint32_t s_addr;    //网络字节序的无符号4字节整数Ip地址                    }                                  }addrlen:addr的大小
返回值:成功:返回0失败:返回-1

2.7.3 listen

头文件:#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>原型:int listen(int sockfd, int backlog);
功能:将套接字设置为被动监听状态
参数:sockfd:文件描述符,socket的返回值backlog:允许同时连接的客户端的个数,一般设置为5,10
返回值:
成功:0
失败:-1

2.7.4 accept

头文件:#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>原型:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:阻塞等待客户端的连接
参数:sockfd:文件描述符,socket的返回值addr:被填充的网络信息结构体,如果由客户端连接服务器,服务器可以通过这个参数获取客户端的信息addrlen:addr的大小
返回值:
成功:返回文件描述符
失败:-1

2.7.5 connect

头文件:#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>原型:int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);功能:给服务器发送连接请求
参数:sockfd:文件描述符,socket的返回值addr:要连接的服务器的网络信息结构体,需要客户端自己填充addrlen:addr的大小
返回值:
成功:返回0
失败:-1

2.8 TCP服务器

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include<arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int main(int argc, char const *argv[])
{//创建套接字int sockfd = socket(AF_INET,SOCK_STREAM,0);  //IPV4协议,流式套接字,具体的协议类型if(-1 == sockfd){perror("socket");return -1;}struct sockaddr_in server_addr;   //保存服务器的信息memset(&server_addr,0,sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(8000);server_addr.sin_addr.s_addr = inet_addr("192.168.98.147");//绑定信息int ret = bind(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr));if(-1 == ret){perror("bind");return -1;}//设置监听队列ret = listen(sockfd,10);if(-1 == ret){perror("listen");return -1;}printf("等待客户端进行连接...、\n");struct sockaddr_in Client_addr;    //用于保存客户端的信息int length = sizeof(Client_addr);int fd = accept(sockfd,(struct sockaddr *)&Client_addr,&length);if(-1 == fd){perror("accept");return -1;}printf("接收客户端的连接 %d\n",fd);char buf[32] = {0};while(1){ret = recv(fd,buf,sizeof(buf),0);if(-1 == ret){perror("recv");return -1;}if(strcmp(buf,"bye") == 0){break;}printf("%s\n",buf);memset(buf,0 ,sizeof(buf));}close(fd);close(sockfd); return 0;
}

2.9 TCP客户端

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include<arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>int main(int argc, char const *argv[])
{//创建套接字int sockfd = socket(AF_INET,SOCK_STREAM,0);if(sockfd == -1){perror("socket");return -1;}//向服务器发起连接struct sockaddr_in server_addr;   //保存服务器的信息memset(&server_addr,0,sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(8000);server_addr.sin_addr.s_addr = inet_addr("192.168.98.147");int ret = connect(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr));if(-1 == ret){perror("connect");return -1;}char buf[32] = {0};while(1){scanf("%s",buf);ret = send(sockfd,buf,strlen(buf),0);if(-1 == ret){perror("send");return -1;}if(strcmp(buf,"bye") == 0){break;}memset(buf,0,sizeof(buf));}close(sockfd);return 0;
}

2.10 TCP并发服务器

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include<arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <pthread.h>
void * ClientHandler(void *arg)
{int ret;int fd = *(int *)arg;char buf[32] = {0};pthread_detach(pthread_self());    //线程结束,自动释放资源while(1){ret = recv(fd,buf,sizeof(buf),0);if(-1 == ret){perror("recv");return (void *)-1;}else if(0 == ret){break;   //客户端异常退出}if(strcmp(buf,"bye") == 0){break;}printf("接收%d客户端 %s\n",fd,buf);memset(buf,0 ,sizeof(buf));}printf("%d 客户端退出!\n",fd);close(fd);
}
int main(int argc, char const *argv[])
{//创建套接字int sockfd = socket(AF_INET,SOCK_STREAM,0);  //IPV4协议,流式套接字,具体的协议类型if(-1 == sockfd){perror("socket");return -1;}struct sockaddr_in server_addr;   //保存服务器的信息memset(&server_addr,0,sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(8000);server_addr.sin_addr.s_addr = inet_addr("192.168.98.147");//绑定信息int ret = bind(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr));if(-1 == ret){perror("bind");return -1;}//设置监听队列ret = listen(sockfd,10);if(-1 == ret){perror("listen");return -1;}printf("等待客户端进行连接...、\n");struct sockaddr_in Client_addr;    //用于保存客户端的信息int length = sizeof(Client_addr);while(1){int fd = accept(sockfd,(struct sockaddr *)&Client_addr,&length);if(-1 == fd){perror("accept");return -1;}printf("接收客户端的连接 %d\n",fd);//为每一个客户端创建新的线程pthread_t tid;ret = pthread_create(&tid,NULL,ClientHandler,&fd);if(ret != 0){perror("pthread_create");return -1;}}close(sockfd); return 0;
}
#!/bin/bashfor ((i=0;i<100;i++))
do./4-Tcp客户端 &sleep 0.1
done

练习:实现客户端下载服务器所在目录文件
客户端发送要下载的文件名给服务器
服务器判断文件是否存在,将结果告知客户端
如果文件存在,服务器读取文件内容,并发送给客户端
客户端收到文件内容并写入指定的文件

2.11 UDP 网络编程

服务器:创建套接字 socket填充服务器网络信息结构体将套接字和网络信息结构体绑定bind进行通信 recvfrom /sendto()
客户端:创建套接字 socket填充网络信息结构体进行通信 recvfrom/sendto

函数接口recvfrom/sendto

------recvfrom

1.recvfrom/sendto
------recvfrom
头文件:#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);
功能:接收数据
参数:前四个和recv一样src_addr:源的地址,接收谁的数据,他的信息会自动填充到这个参数addrlen:src_addr的大小
返回值成功:实际接收的字节数失败: 返回-1
------sendto
头文件:#include <sys/types.h>#include <sys/socket.h>
原型:ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);功能:接收数据
参数:前四个和send一样dest_addr:目的地址,需要自己指定addrlen:dest_addr的大小
返回值成功:发送的字节数失败: 返回-1

//udp服务器

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#define ERRLOG(errmsg) do{\perror(errmsg);\printf("%s - %s - %d\n",__FILE__,__func__,__LINE__);\exit(1);\}while(0)
int main(int argc, char const *argv[])
{int sockfd;//第一步:创建套接字if(-1 == (sockfd = socket(AF_INET,SOCK_DGRAM,0))){ERRLOG("socket error");}struct sockaddr_in serveraddr,clientaddr;socklen_t addrlen = sizeof(serveraddr);//第二步:填充服务器网络信息结构体  serveraddr.sin_family = AF_INET;serveraddr.sin_addr.s_addr = inet_addr("192.168.98.147");serveraddr.sin_port = 8888;//第三步:将套接字与服务器网路信息结构体绑定int ret = bind(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));if(ret == -1){ERRLOG("bind");}//进行通信char buf[32] = {0};while(1){NEXT:if(recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&clientaddr,&addrlen) == -1){ERRLOG("recvfrom");}if(strcmp(buf,"bye") == 0){printf("客户端%s-%d退出了\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));goto NEXT;}printf("%s-%d: %s\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port),buf);}return 0;
}

//udp客户端

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#define ERRLOG(errmsg) do{\perror(errmsg);\printf("%s - %s - %d\n",__FILE__,__func__,__LINE__);\exit(1);\}while(0)
int main(int argc, char const *argv[])
{int sockfd;//第一步:创建套接字if(-1 == (sockfd = socket(AF_INET,SOCK_DGRAM,0))){ERRLOG("socket error");}struct sockaddr_in serveraddr,clientaddr;socklen_t addrlen = sizeof(serveraddr);//第二步:填充服务器网络信息结构体  serveraddr.sin_family = AF_INET;serveraddr.sin_addr.s_addr = inet_addr("192.168.98.147");serveraddr.sin_port = 8888;//进行通信char buf[32] = {0};while(1){scanf("%s",buf);if(sendto(sockfd,buf,32,0,(struct sockaddr *)&serveraddr,addrlen) == -1){ERRLOG("sendto");}if(strcmp(buf,"bye") == 0){printf("客户端退出了\n");}memset(buf,0,sizeof(buf));}return 0;
}

苏嵌实训——day17相关推荐

  1. 【苏嵌实训-嵌入式 linux C 第 1天】

    | 项目名称 [苏嵌实训-嵌入式 linux C 第 1天] 今日进度以及任务 了解未来就业形势.学习Linux系统开发环境,熟悉编译环境和命令. 任务完成情况 通过在微信公众号及百度搜索完成 本日开 ...

  2. 苏嵌实训-嵌入式Linux C 第一天

    项目名称 苏嵌实训-嵌入式Linux C 第一天 今日进度以及任务 嵌入式开发概述及嵌入式LinuxC项目演示 今日开发中出现的问题汇总 1.嵌入式底层开发为什么选择C语言? 2.什么是实时性?硬实时 ...

  3. 苏嵌实训——day2

    文章目录 一.C语言简单讲解 1.1 代码注释 1.2 中英文切换 1.3 代码讲解 gcc编译出现问题的解决方式 二. 计算机的数据表示 数值型数据 非数值型数据 三.词法符号 3.1 关键词 3. ...

  4. 苏嵌实训——day7

    文章目录 一 Makefile简介 1.1什么是Makefile? 1.2什么是make? 1.3为什么使用? 1.4.优越性 二.makefile 2.1 makfile编译规则 2.2 Makef ...

  5. 苏嵌实训——day19

    文章目录 一.数据库 1.1 在ubuntu中安装数据库 1.2 数据库的操作 1.2.1 数据库命令的分类 1.2.2 常用的系统命令 1.2.3 数据中的常用的语句 1.3 sqlite数据库中常 ...

  6. 苏嵌实训——day9

    文章目录 一 单链表 1.1 概念 1.2 单链表的操作 1.2.1 定义结点结构体 1.2.2 创建一个空的单链表 1.2.3 头插法插入数据 1.2.4 遍历单链表 1.2.5 尾插法插入数据 1 ...

  7. 苏嵌实训——day18

    文章目录 一 wirkeshark 抓包工具 1.1 软件介绍 1.2 软件安装 1.3 wireshark工具的使用 1.4 TCP三次握手和四次挥手 二 TCP循环服务器 2.1 IO多路复用 2 ...

  8. 苏嵌实训——day11

    文章目录 一.队列 1.1 队列的概念 1.2 链式队列 1.2.1 linkqueue.h 1.2.2 linkqueue.c 1.3 顺序队列(循环队列) 1.3.1 sequeue.h 1.3. ...

  9. 苏嵌实训——day1

    文章目录 一.概述 二.Linux 三.linux的系统的层次 四.linux目录结构 五.命令行提示符的介绍 六.linux的基本命令 6.1 ls命令 6.2 chmod命令 6.3 cd 命令 ...

最新文章

  1. 蓝牙 socket 建立不了_蓝牙电话之PBAP同步电话簿的安卓实现
  2. 在 aws emr 上,将 hbase table A 的数据,对 key 做 hash,写到另外一张 table B
  3. 图片上传之后清空_OSS文件上传及OSS与ODPS之间数据连通
  4. hdu 5124(线段树区间更新+lazy思想)
  5. 数字图像处理形态学运算
  6. android 5.0 下载编译
  7. h5页面生成图片分享到微信js_html2canvas 动态生成微信分享海报的优质js库
  8. js数字累加 · 递增动画 - 封装篇
  9. 室内布线电缆未来的发展趋势
  10. 资产信息自动化收集系统 Venux
  11. MySQL innodb下的记录锁,间隙锁,next-key锁
  12. nginx反向代理nexus3
  13. 2018CUMCM(数学建模国赛)_B——智能RGV的动态调度策略
  14. 网络地址和广播地址的快速计算方法
  15. maven 阿里下载源 setting.xml
  16. 通过经纬度调用百度sdk api实现查询详细地址 Java
  17. 团队作业——Alpha冲刺 1/12
  18. Oracle触发器(当A表新增/修改/删除时,同步数据到B表)
  19. Linux 基础入门 08
  20. MODBUS通讯详解(博客园)

热门文章

  1. 解决Redisson无法连接Sentinel, Netty查找DNS失败
  2. 专为macbook设计的剩余电池电量提醒工具:Battery Indicator
  3. Java线程安全的有序阻塞队列PriorityBlockingQueue
  4. Ios 11 android 7,安卓8.0发布同时 苹果的iOS 11 beta 7也来了
  5. 儿科主治医师总题库 --- 一例APK脱壳反编译寻找AES密钥过程记录
  6. html的边框阴影的代码是什么,CSS中边框阴影(box-shadow)的实现方法介绍(代码示例)...
  7. oracle查看谁锁表,ORACLE 如何查询哪个用户锁表?
  8. !!?用mod删除服务时显示指定服务未安装
  9. C语言:编写程序,判断某一年是否是闰年
  10. QT--文字超链接和图片显示