树莓派学习:建立socket进行网络通信+tcp+udp+端口+字节序+socketAPI+地址转换API+聊天对话框实战

您所在的位置:网站首页 socket用于描述ip地址和端口 树莓派学习:建立socket进行网络通信+tcp+udp+端口+字节序+socketAPI+地址转换API+聊天对话框实战

树莓派学习:建立socket进行网络通信+tcp+udp+端口+字节序+socketAPI+地址转换API+聊天对话框实战

2024-03-21 11:38| 来源: 网络整理| 查看: 265

目录

socket套接字网络通信学习

数据协议

tcp

udp

ip地址

端口

字节序

步骤

 API介绍

地址转换API

实战  聊天对话框

服务器  运行时后面要传IP地址和端口

客户端   运行时后面要传IP地址和端口

socket套接字网络通信学习 数据协议

socket是网络通信,通信的数据协议有http、tcp、udp等等,简单来说就是传输数据的格式,常用的是tcp和udp

tcp 简单来说就是两个人进行打电话,a和b打电话的意思,要别人接通才可以立刻收到消息进行交流,所以是可靠的,多用在精准控制,要保证传输数据的准确性,所以tcp连接传数据无差错,不丢失,不重复,且有序tcp是面向字节流,实际上是tcp把数据看成一连串无结构的字节流,是全双工的可靠信道tcp只支持一对一通信tcp首部开销20字节 udp 简单来说就是两个人进行发短信,a给b发短信的意思,a不知道b有没有收到,可以不用和b建立通道才发送数据,所以是不可靠的,但udp也不是没有用,因为你要发送视频或者比较大的数据,就可以用到udp,可能中途会有些丢包,但大部分是完整的,视频出现一些小黑点我们也看不见udp是面向报文,udp没有堵塞拥挤,对网络视频那些会有好处,是不可靠信道udp支持一对一,一对多,多对一,多对多通信udp首部开销8个字节

要网络通信,那少不了的就是IP地址和端口号,ip地址是你与谁的机子通信,端口是指机子里的哪个服务通信,一台机子有很多端口

ip地址 ip地址是你的电脑连上wifi,就会分到一个属于自己的ip地址,属于同一个网络下,就可以与另一个ip地址进行通信 端口 端口简单来说就是服务,一台电脑有很多服务,比如web、ftp、smtp等等,别人来找你通信,你ip只有一个,网页又需要通信,vx也要通信,别人发来的数据谁来接收呢,所以一台电脑会分配许多端口来给每个需要通信的服务进行交流,简单来说银行就是ip地址,你进去存钱,你就要进到银行里面的某个窗口办理实际上是通过 “ IP地址 + 端口号 ” 来区分服务的端口提供了一种访问通道,服务器一般是通过知名的端口号来识别,一般某个服务就指定了某个端口,例如ftp服务是21号端口,telnet服务器的端口是23,tftp服务器的端口是69  字节序

字节序是指多字节数据在计算机内存存储或者网络传输时各个字节的存储顺序

LIttle endian 小端字节序Big endian 大端字节序 (网络字节序)

例如存储0x01 0x02 0x03 0x04这四个数据到为 2000 2001 2002 2003这四个地址里

小端存储是 2003--0x01 2002--0x02 2001--0x03 2000--0x04大端存储是 2000--0x01 2001--0x02 2002--0x03 2003--0x04

我们将0x1234abcd写入到以0x0000开始的内存中

          Big endian  LIttle endian0000        0x12        0xcd0001        0x34        0xab0002        0xab        0x340003        0xcd        0x12 步骤

我们只需要调用socket的api进行通信就可以,api会调用内核帮我们实现

tcp server步骤 先建立socket套接字,返回网络描述符,后面会用到进行bind连接,在用之前要为套接字添加信息(IP地址和端口)listen监听,监听网络连接,监听是否有人连接accept接入,监听到有人接入,就接受一个连接数据交流read,writeclose关闭套接字,断开连接tcp client步骤 先建立socket套接字,返回网络描述符,后面会用到connect连接,连接前要知道IP地址和端口数据交流read,writeclose关闭套接字,断开连接  API介绍 头文件 #include #include int socket(int domain,int type, int protocol) 一种可用于根据指定的地址族、数据类型和协议来分配一个套接口的描述字及其所用的资源的函数返回值:非负描述符 – 成功,-1--出错 int bind(int sockfd,const struct sockaddr* myaddr,socklen_t addrlen)int listen(int sockfd,int backlog)int connect(int sockfd,conststruct sockaddr *addr, socklen_t addrlen)int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)ssize_t send(int sockfd,constvoid *buf, size_t len,int flags)ssize_t sendto(int sockfd,const void *buf, size_t len,int flags,const struct sockaddr *dst_addr, socklen_t addrlen)  主要用于udpssize_t recv(int sockfd,void *buf, size_t len,int flags)ssize_t recvfrom(int sockfd,void *buf, size_t len,int flags,struct sockaddr *src_addr, socklen_t *addrlen)   主要用于udpread  write 地址转换API int inet_aton(const char* straddr , struct in_addr *addrp); 把字符串形式的“xxx.xxx.xxx.xxx”转为网络识别模式char* inet_ntoa(struct in_addr inaddr); 把网络识别模式转为字符串形式的“xxx.xxx.xxx.xxx” 实战  聊天对话框 服务器  运行时后面要传IP地址和端口 #include #include #include #include #include #include #include int main(int argc, char **argv) { int s_fd;//服务端描述符 int c_fd;//客户端描述符 int n_read;//读了多少字节 char readBuf[128];//收到的数据缓存 int mark = 0;//记录第几个连接标识符 char msg[128] = {0};//发送的数据缓存 struct sockaddr_in s_addr;//自己服务端的协议机构提 struct sockaddr_in c_addr;//已连接的客户端的协议结构体 //如果后面没有两个参数,退出 if(argc != 3){ printf("param is not good\n"); exit(-1); } memset(&s_addr,0,sizeof(struct sockaddr_in));// memset(&c_addr,0,sizeof(struct sockaddr_in));// //1. 创建socket AF_INET为ipv4协议 SOCK_STREAM为面向连接的通信流,tcp协议,0是自动匹配对应协议 s_fd = socket(AF_INET, SOCK_STREAM, 0); if(s_fd == -1){ perror("socket"); exit(-1); } s_addr.sin_family = AF_INET;//记录上面的协议族ipv4协议 s_addr.sin_port = htons(atoi(argv[2]));//将字符串端口号转为数字然后转为网络字符 inet_aton(argv[1],&s_addr.sin_addr);//将ip地址转为网络字符放到sin_addr里 //2. bind连接 s_fd是socket描述符 &s_addr是存放socket信息的结构体 sizeof...是结构体的大小 bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in)); //3. listen监听 s_fd是socket描述符 10是最多有十个人同时连接 listen(s_fd,10); //4. accept接入 int clen = sizeof(struct sockaddr_in);//是存放socket信息的结构体的大小 while(1){ // s_fd是socket描述符 &c_addr是已连接的客户端的协议结构体 &clen是存放socket信息的结构体的大小 c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen); if(c_fd == -1){ perror("accept"); } mark++;//记录第几个连接标识符 printf("get connect: %s\n",inet_ntoa(c_addr.sin_addr));//打印客户端的IP地址 //创建线程 if(fork() == 0){ //write写 if(fork()==0){//子线程一直循环发送第几个连接对象,等于心跳包 while(1){ sprintf(msg,"welcom No.%d client",mark); write(c_fd,msg,strlen(msg));//向描述符发送msg消息 sleep(3); } } //5. read读 while(1){ memset(readBuf,0,sizeof(readBuf));//清空收到的数据 n_read = read(c_fd, readBuf, 128);//接收描述符对应的socket消息,放到readbuf里,最大读128字节 if(n_read == -1){//等于-1 表示读取错误 perror("read"); }else if(n_read>0){//大于0 表示读到数据 并打印出来 printf("\nget: %d\n",n_read); }else{//其他的表示客户端退出 printf("client quit\n"); break; } } break; } } return 0; } 客户端   运行时后面要传IP地址和端口 #include #include #include #include #include #include #include int main(int argc, char **argv) { int c_fd;//客户端描述符 int n_read;//读了多少字节 char readBuf[128];//收到的数据缓存 int tmp;// char msg[128] = {0};//发送的数据缓存 struct sockaddr_in c_addr;//客户端的协议结构体 memset(&c_addr,0,sizeof(struct sockaddr_in)); if(argc != 3){ printf("param is not good\n"); exit(-1); } printf("%d\n",getpid());//打印当前进程的进程ID //1. socket AF_INET为ipv4协议 SOCK_STREAM为面向连接的通信流,tcp协议,0是自动匹配对应协议 c_fd = socket(AF_INET, SOCK_STREAM, 0); if(c_fd == -1){ perror("socket"); exit(-1); } c_addr.sin_family = AF_INET;//记录上面的协议族ipv4协议 c_addr.sin_port = htons(atoi(argv[2]));//将字符串端口号转为数字然后转为网络字符 inet_aton(argv[1],&c_addr.sin_addr);//将ip地址转为网络字符放到sin_addr里 //2.connect c_fd是socket描述符 &c_addr是存放socket信息的结构体 sizeof...是结构体的大小 if(connect(c_fd, (struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1){ perror("connect"); exit(-1); } while(1){ if(fork()==0){//子线程 while(1){//不断获取来自键盘的消息并且发送出去 memset(msg,0,sizeof(msg)); printf("input: "); gets(msg);// write(c_fd,msg,strlen(msg));//向描述符发送msg消息 } } while(1){// memset(readBuf,0,sizeof(readBuf)); n_read = read(c_fd, readBuf, 128);//接收描述符对应的socket消息,放到readbuf里,最大读128字节 if(n_read == -1){ perror("read");//等于-1 表示读取错误 }else{ printf("\nget:%s\n",readBuf);//大于0 表示读到数据 并打印出来 } } } return 0; }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3