网络编程
一、进程间通信方式
1、信号 kill -信号值 pid / killall -信号值 进程名 / killall signal() 2、无名管道 – 不存在与文件系统,只能作用于亲缘进程。 3、有名管道 – 是Linux系统中的一种特殊文件(管道文件),可以实现同一主机内任意两个进程之间的通信。写入具有原子性。可以实现多对一通信。 4、消息队列 – 消息带有类型的一种”管道” 5、共享内存 – 进程间通信最快的一种方式, 6、信号量 – 结合共享内存使用
二、网络编程 – 套接字编程
本质:在不同的主机上的进程通过网络协议实现通信。
1、套接字
套接字是网络通信中重要的接口,可以把它理解成Linux的一种特殊的文件描述符。 套接字既可以实现本地之间进程间通信,也可以实现网络间进程间通信。
2、协议
在不同的主机间进行通信,那么通信双方必须对通信的内容有相同的理解,需要通信双方遵循同一个约定,这个约定就是协议!
Internet 的前身是阿帕网(ARPAnet), 阿帕网使用的协议是 NCP协议。 阿帕网缺点:不能互联不同操作系统的计算机。 1983年被TCP/IP 协议取代
TCP:传输控制协议,检查网络通信中的错误。
IP:因特网互联协议,对不同的主机实现互联。
3、网络体系模型
OSI七层模型 TCP/IP四层模型
4、传输层协议 TCP / UDP
1)TCP协议 (打电话) 面向连接 : 在通信之前要先建立连接 可靠的传输协议 : 保证数据无丢失,无错漏,无重复到达。 应用场景: ·传输质量高或者是大数据传输通信时。 ·即时通讯软件登录。 ·可靠数据传输场合。
2)UDP协议 (寄信) 面向非连接:在通信之前不需要连接 不可靠传输协议:数据保证正常发送,但是不保证一定被对方正确接收。 应用场景: ·发送小尺寸数据。 ·用于广播和组播 ·网络流媒体数据传输一般采用UDP协议。
5、几个网络编程的基本知识
1) socket 套接字 --> 一个特殊的文件描述符 ·一个函数接口 ·在网络体系模型中,socket位于用户层(应用层)和内核(传输层)之间,TCP和UDP都支持套接字。 ·Linux下的文件描述符,可以通过read,write,close进行操作
2)IP地址 ·在IP协议中规定,所有Internet上进行通信的主机都必须要一个IP地址。 ·在IPV4协议中,IP地址是一个32位无符号整数。 unsigned int ·网络上的数据包中必须包含源IP和目标IP ·IP地址通常使用点分十进制表示 : “192.168.15.2”
3)端口号 (unsigned short) 0 ~ 65535 端口号作用:当一个网络数据包传输到主机时,通过数据包上的端口号信息确定发给对应的进程。 端口号使用情况: 1)系统占用端口号 : 0 ~ 1023 2)可用端口号 : 1024 ~ 65535
FTP: 20 21 telnet : 23
4)字节序 小端序:高位存放高位地址,低位数据存放低位地址 (主机字节序) 大端序:高位存放低位地址,低位数据存放高位地址 (网络字节序)
例子: 假设有一个数据 0x12345678,存放在连续的四个字节中, 0xaabbcc00, 0xaabbcc01, 0xaabbcc02,0xaabbcc03, 请问这个数据中每个字节的存放情况(小端序)。 ==> 012, 0x34, 0x56, 0x78 ==> 0x12 (最高位数据) ==> 0xaabbcc00, 0xaabbcc01, 0xaabbcc02,0xaabbcc03, ==> 0xaabbcc03 (最高位地址) ==> 0x12 == 0xaabbcc03; ==> 0x34 == 0xaabbcc02; ==> 0x56 == 0xaabbcc01; ==> 0x78 == 0xaabbcc00; 注意:在通信时,需要把主机字节序的IP和端口号设置成网络字节序
三、计算机IP设置
1、Windows 的IP设置
1) 查看自己的IP
3)修改自己的IP
2,Ubuntu的IP设置 ==> 查看自己的IP信息 ifconfig
==> 临时设置IP sudo ifconfig ens33 192.168.15.xx (自己分配的IP)
Ubuntu的IP永久设置 --《Ubuntu16.04网络设置》
3、开发板IP设置
四、TCP网络通信
1、分析TCP通信的C/S模型 client/server
TCP传输协议要求通信双方在通信时先建立连接。C/S模型中使用的就是TCP通信协议。
2、相关函数
1) socket() //获取一个套接字
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
==> domain : 地址协议族 AF_INET (IPV4) ==> type : 传输层的协议类型 SOCK_STREAM : 流式套接字 TCP协议 SOCK_DGRAM : 数据报套接字 UDP协议 ==> protocol : 默认属性 0 返回值: 成功返回套接字,失败返回-1
2) Bind() //给套接字绑定一个IP和端口号
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
==> sockfd : 套接字 ==> addr : 通用地址结构体指针 ==> addrlen : 通用地址结构体大小 返回值:成功返回0,失败返回-1 通用地址结构
struct sockaddr
{
u_short sa_family; // 地址族, AF_xxx
char sa_data[14]; // 14字节协议地址
};
Internet协议地址结构 IPV4地址结构体
struct in_addr
{
in_addr_t s_addr; // u32 network address
};
struct sockaddr_in
{
u_short sin_family; // 地址族, AF_INET,2 bytes
u_short sin_port; // 端口,2 bytes
struct in_addr sin_addr; // IPV4地址,4 bytes
char sin_zero[8]; // 8 bytes unused,作为填充
};
3) listen() // 监听套接字
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);
==> sockfd : 套接字 ==> backlog : 监听数量 ==> 监听套接字同时能连接的客户端的最大数(backlog+4) 返回值:成功返回0,失败返回-1
4) accept() //等待连接
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
==> sockfd : 套接字 ==> addr : 地址结构体变量地址 (存放发起连接方的IP地址信息) ==> addrlen : 存放地址结构体变量大小 返回值: 成功返回一个会话ID,失败返回-1;
5) connect() //发起连接
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
==> sockfd : TCP套接字 ==> addr : 存放对方地址信息的结构体的地址 ==> addrlen : 地址结构体大小 返回值:成功返回0,失败返回-1;
6)write/read
例子: 设计一个C/S模型,客户端连接服务器,然后循环获取数据发送给服务器,服务器接收数据就把数据打印出来,如果发送 “QUIT_TALK\n”, 服务器和客户端都退出。
服务器
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == sockfd)
{
perror("socket failed");
return -1;
}
struct sockaddr_in server_addr, client_addr;
socklen_t addrlen = sizeof(server_addr);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8888);
server_addr.sin_addr.s_addr = inet_addr("192.168.15.3");
if(bind(sockfd, (struct sockaddr *)&server_addr, addrlen) < 0)
{
perror("bind failed");
return -1;
}
listen(sockfd, 5);
int talkfd = accept(sockfd, (struct sockaddr *)&client_addr, &addrlen);
char buf[1024];
while(1)
{
memset(buf, 0, sizeof(buf));
read(talkfd, buf, sizeof(buf));
if( strcmp(buf, "QUIT_TALK\n") == 0 )
break;
printf("recvbuf:%s", buf);
}
close(talkfd);
close(sockfd);
return 0;
}
客户端
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == sockfd)
{
perror("socket failed");
return -1;
}
struct sockaddr_in server_addr;
socklen_t addrlen = sizeof(server_addr);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8888);
server_addr.sin_addr.s_addr = inet_addr("192.168.15.3");
connect(sockfd, (struct sockaddr *)&server_addr, addrlen);
char buf[1024];
while(1)
{
memset(buf, 0, sizeof(buf));
fgets(buf, sizeof(buf), stdin);
write(sockfd, buf, sizeof(buf));
if( strcmp(buf, "QUIT_TALK\n") == 0 )
break;
}
close(sockfd);
return 0;
}
|