一、前言:
对于网络编程这个基础知识,想必大家都不陌生,网上资料也非常多!但是大多数的资料都比较零散;所以本专题也是记录自己的学习笔记,同时也是系统学习一下网络编程,不光是理论,更重要的是也要实践!
二、网络编程的本质:
网络编程的本质就是使用操作系统提供的接口函数来进行编程,然后使得应用程序具备收发网络数据的能力!
在上面这副操作系统图中,有内核和应用程序两个大的模块:
-
我们先来看一下内核:操作系统中的内核主要用来管理硬件的,其中的一个硬件就是网卡!要联网和收发网络数据,我们必须依赖这个硬件网卡才行。
-
而我们的应用程序在被执行之后,它想要去收发网络数据的话,那它该如何做呢?它必须通过内核提供的网络接口,来间接的通过内核控制网卡来实现网络数据的收发!
三、网络编程核心概念:
-
协议:为进行数据通信而预定义的数据规则;要使得通信双方能够正常的通信,必须要有一个规则,而这个规则就是协议了,而这个协议是程序员按照某个标准进行定义的!
-
地址:网络通信中的用于标识设备的整数值。比如我们常见的IP地址:192.168.1.100
-
端口号:设备为收发数据而指定的数值,用于标识具体连接,可以理解为设备中用于网络通信的数据通道!比如说,我们往80端口进行发送数据!
-
角色:服务端:等待连接的设备;客户端:发起连接的设备
-
小端系统:采用的是小端模式(little-endian)的系统,也就是:数据低字节放在内存低地址中,比如说,有一个4个字节的int类型整型值:
0x12345678
那这个整型值在内存中是怎样存放的呢? 这个要看在什么系统下放了,比如这里是在小端系统里面存放的话,应该是这样去存放的:
- 大端系统:采用大端模式(big-endian)的系统,也就是:数据低字节放在内存高地址中,我们还是以刚才的例子来举例:
- 网络字节序:网络字节顺序采用大端模式,所以在小端系统中需要去做一个字节转换才行,不然的话,a设备发送的数据,到达b设备的时候,数据可能就发生了变化,那么这个变化就是字节序所造成的问题,所以要进行一个字节序转换!
四、实际代码案例:
我们现在来实现一个客户端向服务器发送请求,然后服务器收到了这个请求之后,就会给客户端返回一些东西:比如下面这个图片里面所示的请求:
在写代码案例之前,先给大家画一个整体的框架流程:
- 准备连接网络(socket)
- 连接远程设备(connect)
- 收发数据(send/recv)
- 关闭连接(close)
相关网络编程接口初探:
#include <sys/types.h>
#include <sys/socket.h>
函数原型 | 功能描述 |
---|---|
int socket(int domain, int type, int protocal); | 创建套接字,为网络连接做准备 |
int connect(int sock, struct sockaddr *addr, socklen_t len); | 连接指定地址的远程设备 |
– | – |
ssize_t send(int fd, const void* buf, size_t n, int flags); | 发送数据到远程设备 |
ssize_t recv(int fd, void *buf, size_t n, int flags); | 接受远程设备发回的数据 |
int close(int fd); | 销毁套接字 |
下面举例一个小demo案例,向百度服务器发送请求,然后服务器返回对应的信息:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
int sock =0;
int len = 0;
int r = 0;
char buffer[128] = {0};
struct sockaddr_in addr = {0};
char *tosend = "GET /index.html HTTP/1.1\nHOST: www.baidu.com\nUser-Agent: TEST\nConnection: close\n\n";
sock = socket(PF_INET,SOCK_STREAM,0);
if(sock == -1)
{
printf("socket error\n");
return -1;
}
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("39.156.66.10");
addr.sin_port = htons(80);
if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1)
{
printf("connect error\n");
return -1;
}
printf("connect success\n");
len = send(sock, tosend,strlen(tosend),0);
printf("send bytes = %d\n",len);
len = 0;
do
{
int i =0;
r = recv(sock, buffer, sizeof(buffer),0);
if(r>0)
{
len += r;
}
for(i=0;i<r;i++)
{
printf("%c",buffer[i]);
}
}while(r >0)
printf("\n");
printf("recv bytes = %d\n",len);
close(sock);
return 0;
}
最后效果如下:
好了,本期的网络编程基础概念就分享到这里了,我们下期继续分享!