2019年8月16日星期五
一. 网络编程学习大纲
1. 网络编程专业术语,socket概念。
2. 网络编程通信协议:TCP协议/UDP协议。
3. 网络编程IO模型。
4. 网络编程设置套接字属性 -> 广播和超时。
二. 网络编程专业术语,socket概念。
1. 系统编程进程之间通信与网络编程区别?
系统编程进程通信方式: 管道/信号/消息队列/共享内存 -> 特点: 只能在同一台主机内部通信。
网络编程进程通信方式: 套接字 -> 特点: 可以实现同一个局域网中不同主机之间通信。
2. 网络体系结构模型
OSI模型
1)应用层 -> 老板想说的话
2)表示层 -> 将老板想说的话写成一封信
3)会话层 -> 将信塞到信封里,并写上对方的地址
4)传输层 -> 邮差如何将这封信送给对方 -> TCP协议/UDP协议
5)网络层 -> 邮差分析地址是在哪里 -> IP协议 -> Internet Protocol
6)数据链路层 -> 选择一条线路进行传输
7)物理层 -> 出发!
TCP/IP协议模型
1)应用层 -> 老板把想说的话,写进信中,然后封在一个信封。
2)传输层 -> 邮差如何将这封信送给对方 -> TCP协议/UDP协议
3)网络层 -> 邮差分析地址是在哪里 -> IP协议
4)网络接口与物理层 -> 选择一条线路并出发。
3. 传输层TCP协议与UDP协议有什么区别?
TCP协议 -> Tranmission Control Protocol 传输控制协议 -> 面向有连接套接字编程。(打电话)
UDP协议 -> User Data Protocol 用户数据包协议 -> 面向无连接套接字编程。(寄信)
4. 什么是socket?
socket在英文被翻译为套接字,排插,插座。(因为插座种类有很多种,就好像很多种协议)
socket还是一种特殊的文件描述符。(因为socket套接字文件描述符不能通过open函数得到)
socket还是一个创建套接字的函数。
正常来讲,文件描述符是通过open()得到的。
例子: int fd = open("1.txt"); -> fd就是代表"1.txt"的文件描述符。
套接字的文件描述符怎么来的?
例子: int sockfd = socket(TCP协议); -> sockfd就是TCP协议的套接字
5. 什么是IP地址?
例子: "192.168.90.2"
在一个局域网中,每一台主机都会有一个IP地址,这个IP地址就是这台主机唯一的标识符。
每一个IP地址都是32位。
6. 什么是端口号?
在一个局域网中,两个主机之间需要通信,除了IP地址要在同一个局域网中之外,还需要两者使用同一个端口号。
系统已经占用的端口号: 0~1023 (用户不能使用)
用户有效的端口号: 1024~65535 (用户可以使用)
端口号是16位。
例子: 主机A --> 主机B
IP地址必须在同一个网段 192.168.90.2 192.168.90.19
端口号必须一致 50001 50001
三. 永久设置Ubuntu的IP地址?
1. 查看当前Ubuntu的IP地址是多少?
gec@ubuntu:~$ ifconfig
lo Link encap:Local Loopback -> 当前只有lo回环IP,没有以太网卡,需要主动激活网卡。
inet addr:127.0.0.1 Mask:255.0.0.0
2. 激活以太网
gec@ubuntu:~$ sudo ifconfig eth0 up
3. 再次查看
gec@ubuntu:~$ ifconfig
eth0 Link encap:Ethernet HWaddr 00:0c:29:5d:9c:76
inet6 addr: fe80::20c:29ff:fe5d:9c76/64 Scope:Link -> 已经激活以太网卡,但是还没设置IP地址。
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
4. 打开设置IP地址的配置文件
gec@ubuntu:~$ sudo vi /etc/network/interfaces
auto lo
iface lo inet loopback
audo eth0 -> 修改: auto eth0
iface eth0 inet static
address 192.168.0.245 -> 修改:address 192.168.90.xx
gateway 192.168.0.1 -> 修改:gateway 192.168.90.1
netmask 255.255.255.0
保存退出!
5. 重启网络
gec@ubuntu:~$ sudo /etc/init.d/networking restart
* Running /etc/init.d/networking restart is deprecated because it may not enable again some interfaces
* Reconfiguring network interfaces... [OK]
6. 重启虚拟机,再次查看IP地址
gec@ubuntu:~$ ifconfig
eth0 Link encap:Ethernet HWaddr 00:0c:29:5d:9c:76
inet addr:192.168.90.4 Bcast:192.168.90.255 Mask:255.255.255.0
练习1: 设置IP地址
练习2: windows/ubuntu/ARM互相ping通。
三. 网络编程的通信协议 - TCP协议
1. TCP协议特点:
1)TCP协议属于网络体系结构模型传输层。
2)TCP协议可靠的连接方式,面向有连接,也就是客户端必须与服务器连接上了,才能进行通信。
3)TCP协议一般作用文件传输、账号登陆..
2. TCP服务器过程?
1)创建一个未连接套接字? -> socket()
int sockfd;
sockfd = socket(AF_INET,SOCK_STREAM,0);
printf("sockfd = %d ",sockfd); //3
2)绑定IP地址,端口号,协议到未连接套接字。 -> bind()
/* Address to accept any incoming messages. */
#define INADDR_ANY ((unsigned long int) 0x00000000) -> 自动获取主机的IP地址。
struct sockaddr_in srvaddr;
socklen_t len = sizeof(srvaddr);
bzero(&srvaddr,len);
srvaddr.sin_family = AF_INET; //协议
srvaddr.sin_port = htons(atoi(argv[1])); //端口号
srvaddr.sin_addr.s_addr = htonl(INADDR_ANY); //服务器的IP
bind(sockfd,(struct sockaddr *)&srvaddr,len);
3)设置监听套接字 -> listen()
listen(sockfd,5);
4)等待客户端发起连接 -> accept()
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
char *inet_ntoa(struct in_addr in);
struct sockaddr_in cliaddr;
int connfd;
connfd = accept(sockfd,(struct sockaddr *)&cliaddr,&len); //阻塞!
if(connfd > 0)
{
printf("new connection:%s ",(char *)inet_ntoa(cliaddr.sin_addr));
}
5)接收客户端的消息
char buf[50];
while(1)
{
bzero(buf,sizeof(buf));
recv(connfd,buf,sizeof(buf),0);
printf("from Jack:%s",buf);
if(strncmp(buf,"quit",4) == 0)
{
break;
}
}
6)关闭套接字
close(connfd);
close(sockfd);
3. TCP客户端过程?
1)创建一个未连接套接字? -> socket()
int sockfd;
sockfd = socket(AF_INET,SOCK_STREAM,0);
printf("sockfd = %d ",sockfd); //3
2)直接发起连接
struct sockaddr_in srvaddr;
socklen_t len = sizeof(srvaddr);
bzero(&srvaddr,len);
srvaddr.sin_family = AF_INET;//协议
srvaddr.sin_port = htons(atoi(argv[2]));
inet_pton(AF_INET,argv[1],&srvaddr.sin_addr);
int ret = connect(sockfd,(struct sockaddr *)&srvaddr,len);
if(ret == -1)
printf("connnect error! ");
3)不断发送数据
char buf[50];
while(1)
{
bzero(buf,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
send(sockfd,buf,strlen(buf),0);
if(strncmp(buf,"quit",4) == 0)
{
break;
}
}
4)挂断电话
close(sockfd);
练习1:自己跟自己通信。
练习2:自己跟同桌通信。
练习3:尝试写一个回射服务器。
char buf[50];
while(1)
{
bzero(buf,sizeof(buf));
recv(connfd,buf,sizeof(buf),0); -> 客户端发送什么数据过来
send(connfd,buf,strlen(buf),0); -> 就回发什么数据给客户端
if(strncmp(buf,"quit",4) == 0)
{
break;
}
}
练习4:实现客户端与服务器之间进行收和发!