1.套接字socket编程:网络通信程序的编写
网络通信程序的编写使用的都是套接字接口 网络通信程序的编写:TCP/IP五层中应用层是面向程序员的一层,应用层的协议都是程序员自己订立,应用层处理完毕后,将数据交给操作系统,进行传输层开始往下的封装。 传输层的典型协议:UDP/TCP
2.UDP协议和TCP协议的区别
UDP协议:用户数据包协议-----无连接的,不可靠的,面向数据包的一种传输方式(无法提供可靠传输,但是传输速度快)–视频传输 TCP协议:传输控制协议----基于连接的,可靠的,面向字节流的一种传输方式(提供可靠传输,但是传输速度较慢)–普通的文件传输
3.UDP通信程序的编写
在网络通信中,都是端与端之间的通信,两台主机的两个进程间的通信,并且通信两端有一种叫法:
客户端:通信两端中,首先主动发起请求的一端 服务端:通信两端中,首先被动接受请求的一端
4.通信流程
server(服务端)1.在程序中创建套接字—使进程与网卡之间通过套接字建立联系2.为套接字绑定地址信息 ①地址信息:IP地址和端口 ②每一条网络中的数据都要包含:源端IP,PORT,对端IP,PORT ③接收端:告诉操作系统发往这个主机的那个端口的数据应该交给我处理 ④发送端:告诉操作系统,发送的这条数据的源端地址是什么 ⑤就是在创建套接字创建的socket结构体中描述地址信息 3.服务端首先接收数据 ①创建套接字,实际上在内核中创建了一个结构体–socket,socket中会有两个缓冲区(发送/接收) ②一旦网卡接收到数据,这时候操作系统会根据数据中的目的地址信息,去socket列表中进行匹配,这个数据应该放到谁的接收缓冲区中 ③接收数据,只是通过接收接口直接从指定的socket接收缓冲区中取出数据 4.发送数据:将数据放到指定socket的发送缓冲区中,操作系统会在何时的时候,从缓冲分区中取出数据进行封装,最后传输出去5.关闭套接字,释放资源 client(客户端)1.创建套接字,在内核中创建socket结构体2.为套接字绑定地址信息(不推荐) ①刻画段不推荐程序员主动绑定地址,因为一个端口执行被一个进程占用,一旦要绑定的端口已经被使用,则会绑定失败 ②尽可能的避免了地址冲突的概率
5.接口介绍
① 创建套接字:在内核中创建socket结构体 int socket(int domain, int type, int protocol);
domain:地址域类型(地址有各种结构—ipv4,ipv6,local)–表示这是一个什么样通信套接字 AF_INET—ipv4协议版本的地址域
type:套接字类型(SOCKET_STREAM—流式套接字—默认协议是tcp,SOCKET_DGRAM—数据报套接字—默认是udp)
protocol:协议类型—0表示要解字类型的默认协议;IPPROTO_TCP-6 / IPPROT_UDP-17
返回值:返回套接字操作句柄—文件描述符;失败返回-1
② 为套接字绑定地址信息:在创建的socket结构体中描述源端的地址信息,告诉操作系统那些数据放到自己的接收缓冲区int bind(int sockfd, struct sockaddr*addr, socklen_t len)sockfd:创建套接字返回的操作句柄addr:要绑定的地址信息----struct sockaddr 通用地址结构(通常不用这个)–len:地址信息长度ipv4使用的是struct sockaddr_in{sin_family—地址域类型;sin_port—网络字节序端口;sin_addr.s_addr–网络字节序IP地址}
6.UDP实现
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc
, char* argv
[])
{
if(argc
!= 3)
{
printf("usage:./udp_cli 192.169.*.* 9000");
return -1;
}
char* ip
= argv
[1];
uint16_t port
= atoi(argv
[2]);
int sockfd
= socket(AF_INET
,SOCK_DGRAM
, IPPROTO_UDP
);
if(sockfd
< 0)
{
perror("socket perror");
return -1;
}
struct sockaddr_in addr
;
addr
.sin_family
= AF_INET
;
addr
.sin_port
= htons(port
);
addr
.sin_addr
.s_addr
= inet_addr(ip
);
socklen_t len
= sizeof(addr
);
int ret
= bind(sockfd
, (struct sockaddr
*)&addr
, len
);
if(ret
< 0)
{
perror("bind error");
return -1;
}
return 0;