一.网络编程概述
1.概述
网络通信手段的一种,我们在之前学了进程间通信,包括管道、消息队列、共享内存、信号和信号量,这些通信方式有一个共同的特点,就是他们都是在依赖Linux内核在单机上进行进程的通信,而面对多机之间的通信,这些手段就远远不够了。所以我们引入网络,利用网络来实现多机之间的通信。
多机通信有好多例子,比如Linux服务器和Adroid、 IOS、C51、x86的Linux之间的通信。 既然谈到网络编程,就一定需要地址,包括IP地址和端口号。IP地址用来标识一台设备,端口号用来标识一台设备上的进程。除了这个,还需要协议来作为支撑,包括TCP、UDP和HTTP协议等,协议作为一种规则,约定了通信双方的数据格式,就好比两个人必须都用中文才能听懂对方说话。
我们在这里主要用到的是Socket网络编程,也叫套接字网络编程,主要用到TCP和UDP协议。
2.TCP/UDP
1、TCP面向连接(如打电话要先拨号建立连接) ;UDP是无连接的,即发送数据之前不需要建立连接
2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)
4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多, 多对一和多对多的交互通信
5、TCP首部开销20字节;UDP的首部开销小,只有8个字节
6、TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道
3.端口号作用
一台拥有IP地址的主机可以提供许多服务,比如Web服务、FTP服务、SMTP服务等。
这些服务完全可以通过1个IP地址来实现。那么,主机是怎样区分不同的网络服务呢?显然不能只靠IP地址,因为IP 地址与网络服务的关系是一对多的关系。
实际上是通过“IP地址+端口号”来区 分不同的服务的。端口提供了一种访问通道,服务器一般都是通过知名端口号来识别的。例如,对于每个TCP/IP实现来说,FTP服务器的TCP端口号都是21,每个Telnet服务器的TCP端口号都是23,每个TFTP(简单文件传送协议)服务器的UDP端口号都是69。3000以下的端口号一般是操作系统所使用的,用户一般使用5000到9000的端口号。
二.字节序
字节序是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序。
字节序分为小端字节序和大端字节序:
- Little endian:将低序字节存储在起始地址
- Big endian:将高序字节存储在起始地址
TCP/IP协议规定,网络数据流应采用大端字节序
为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换:
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
//h表示host,n表示network,l表示32位长整数,s表示16位短整数。
//如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回,如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回。
注意,网络字节序指的是大端字节序。
三.socket编程步骤
1.创建套接字—socket()
2.为套接字添加信息(IP地址和端口号)—bind()
3.监听网络连接—listen()
4.监听到有客户端接入,接受一个连接—accept()
5.数据交互
6.关闭套接字,断开连接
四.linux提供的API简析
1.连接协议
int socket(int domain, int type, int protocol);
(1)domain:通常是AF_INET,指IPV4因特网域
(2)type:指定socket类型,SOCK_STREAM它使用TCP协议,SOCK_DGRAM使用UDP协议
(3)protocol:0默认选择type对应的协议
创建失败返回-1.
2.连接地址
int bind(int sockfd, const struct sockaddr *maddr,socklen_t addrlen);
(1)sockfd:网络标识符
(2)struct sockaddr_in{
sa_family_t sin_family; //指定AF_***,表示使用什么协议族的ip格式
in_port_in sin_port; //设置端口号
struct in_addr sin_addr; //设置ip
unsigned char sin_zero[8];
};
(3)结构体大小
3. 地址转换API
把字符串形式的“192.168.1.123”转为网络能识别的格式:
int inet_aton(const char* straddr,struct in_addr *addrp);
网络格式的ip地址转为字符串形式:
char* inet_ntoa(struct in_addr inaddr);
4.监听
int listen(int sockfd,int backlog)
(1)sockfd:网络连接号
(2)backlog:指定请求队列中同时最大请求数
文章来源:https://www.toymoban.com/news/detail-657924.html
5.连接
int accept(int sockfd,struct sockaddr *addr,socklen_t addrlen)
(1)网络连接号
(2)客户端地址,NULL
(3)客户端地址长度,NULL(指针) 返回值是新建立的通道。
6.数据收发
文章来源地址https://www.toymoban.com/news/detail-657924.html
7.客户端的connect函数
connect(int sockfd,const struct sockaddr *addr,socklen_t addrlen)
(1)目的服务器端口号
(2)服务器的IP地址和端口号的结构体
(3)地址长度
五.socket服务端编程
//server.c
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
//int socket(int domain, int type, int protocol);
//int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
int main()
{
int s_fd;
int n_read;
char readBuf[128];
char *msg = "I get your message";
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
memset(&s_addr,0,sizeof(struct sockaddr_in));
memset(&c_addr,
到了这里,关于linux 网络编程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!