网络编程套接字socket简单用法

xiaoxiao2021-02-28  37

一、IP地址

1、什么是IP地址

IP地址是指计算机在网络上的地址,一台计算机可以有多个IP地址(看网卡上配置了多少个地址),通过IP地址,一台计算机可以找到远在千里之外的另一台计算机,并将信息投递给它。IP地址对应IP协议,IP协议工作在OSI七层模型中的网络层。

2、IP报文结构(IPv4)

我们先来看看IP报文结构图:

(1)版本字段:长度为4位,表示所使用的网络层IP的版本号。版本字段值为4,表示IPv4;值为6,表示IPv6。 (2)报文长度:长度字段为4位,IP分组的分组长度在20~60字节;IP分组的分组头必须是4字节的整数倍,如果不是,则由填充字段“添0”补充。 (3)服务类型:长度为8位,用于指示路由器如何处理该分组。服务类型由4位服务类型字段和3为优先级字段构成,有1位的保留位 (4)总长度:长度为16位,它定义的是以字节为单位的分组总长度,是报文长度与数据长度之和。他表示的IP分组的最大长度为65535字节。 (5)生存时间TTL:设置了数据包可以经过的路由器数目。一旦经过一个路由器,TTL的值就会减1,当该字段为0时,数据包被抛弃。 (6)头校验和:字段长度为8位,设置头部校验和是为了保证分组头部的数据完整性 (7)协议字段:字段长度为8位,指使用IP的高层协议类型。 (8)标识符字段:字段长度为16位,标识ID是片识别的标记,主要是为了防止出现片混乱现象。 (9)片偏移字段:长度为13位,表示分片在整个分组中的相对位置。

3、IP地址分类

为了便于寻址以及层次化构造网络,每个IP地址包括两个标识码(ID),即网络ID和主机ID。同一个物理网络上的所有主机都使用同一个网络ID,网络上的一个主机(包括网络上工作站,服务器和路由器等)有一个主机ID与其对应。Internet委员会定义了5种IP地址类型以适合不同容量的网络,即A类~E类。

4、IP地址的组成

IP地址由两部分组成,网络部分和主机部分,比如:

二、端口号

1、基本概念

如果把IP地址比作一间房子 ,端口就是出入这间房子的门。真正的房子只有几个门,但是一个IP地址的端口 可以有65536(即:256×256)个之多!端口是通过端口号来标记的,端口号只有整数,范围是从0 到65535(256×256)。 (1)端口号是一个2字节16位的整数,用来标识一个进程,告诉操作系统当前的数据要交给哪一个进程来处理。 (2)IP地址用于标识一个主机的地址,端口号用于标识进程,所以IP地址+端口号能够标识网络上的某一台主机的某一个进程。 (3)一个端口号只能被一个进程占用。

2、理解“端口号”与“进程ID”

进程ID表示唯一一个进程,端口号也标识一个进程,那么端口号与进程ID之间有什么关联呢? 端口号与进程ID的关系就相当于工号与身份证号的关系; 一个进程可以绑定多个端口号,但是一个端口号只能被一个进程占用。

3、源端口号和目的端口号

源端口标识发起通信的那个进程,目的端口标识接受通信的那个进程。有了端口号,接受到报文后才能够知道将报文发送到哪个进程。

三、TCP协议

TCP是TCP/IP协议栈中的传输层的协议,TCP协议又叫传输控制协议(Transport Control Protocal),是面向连接的,可靠的字节流服务。

四、UDP协议

UDP是传输层协议,和TCP协议处于一个分层中,但是与TCP协议不同,UDP协议并不提供超时重传,出错重传等功能,也就是说其是不可靠的协议。

五、网络字节序

1、基本概念

网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian(大端)排序方式。 字节序可分为两类: a) Little-Endian:就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。 b) Big-Endian:就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

2、几种转换函数(网络字节序与主机字节序的转换)

#include<arpa/inet.h> unit32_t htonl(unit32_t hostlong); unit16_t htons(unit16_t hostshort); unit32_t ntohl(unit32_t netlong); unit16_t ntohs(unit16_t netshort);

这些函数名很好记,h表示host,n表⽰示network,l表示32位长整数,s表示16位短整数。 例如htonl表示将32位的长整数从主机字节序转换为网络字节序,例如将IP地址转换后准备发送。 如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回; 如果主机是大端字节序,这些 函数不做转换,将参数原封不动地返回

六、socket编程接口

1、创建socket文件描述符

函数说明:domain:表示协议簇 type:协议类型 protocol:协议编号 返回值:调用成功,返回一个标识该套接字的文件描述符,失败返回-1.

2、绑定端口号

函数说明: sockfd:用socket函数创建的文件描述符。 addr:指向一个结构为sockaddr参数的指针,sockaddr包含了地址、端口和IP地址等信息。

3、监听socket

4、接收请求

5、建立连接

sockaddr 结构 sockaddr_in 结构

七、简单的UDP网络程序

client.c(客户端)

1 #include<stdio.h> 2 #include<sys/socket.h> 3 #include<string.h> 4 #include<stdlib.h> 5 #include<sys/types.h> 6 #include<netinet/in.h> 7 #include<arpa/inet.h> 8 9 10 int main(int argc,char* argv[]) 11 { 12 int sock=socket(AF_INET,SOCK_DGRAM,0); 13 if(sock<0) 14 { 15 perror("socket"); 16 return 2; 17 } 18 19 struct sockaddr_in server; 20 server.sin_family=AF_INET; 21 server.sin_port=htons(atoi(argv[2])); 22 server.sin_addr.s_addr=inet_addr(argv[1]); 23 24 char buf[1024]; 25 struct sockaddr_in peer; 26 while(1) 27 { 28 socklen_t len=sizeof(peer); 29 printf("Please Enter#"); 30 fflush(stdout); 31 ssize_t s=read(0,buf,sizeof(buf)-1); 32 if(s>0) 33 { 34 buf[s-1]=0; 35 sendto(sock,buf,strlen(buf),0,\ 36 (struct sockaddr*)&server,sizeof(server)); 37 ssize_t _s = recvfrom(sock, buf, sizeof(buf)-1, 0,\ 38 (struct sockaddr*)&peer, &len); 39 if(_s>0) 40 { 41 buf[_s]=0; 42 printf("server echo# %s\n",buf); 43 } 44 } 45 } 46 }

server.c(服务器端)

1 #include<stdio.h> 2 #include<sys/socket.h> 3 #include<string.h> 4 #include<netinet/in.h> 5 #include<arpa/inet.h> 6 #include<stdlib.h> 7 #include<sys/types.h> 8 9 int main(int argc, char* argv[]) 10 { 11 int sock=socket(AF_INET,SOCK_DGRAM,0); 12 if(sock<0){ 13 perror("socket"); 14 return 2; 15 } 16 17 struct sockaddr_in local; 18 local.sin_family=AF_INET; 19 local.sin_port=htons(atoi(argv[2])); 20 local.sin_addr.s_addr=inet_addr(argv[1]); 21 22 if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0) 23 { 24 perror("bind"); 25 return 3; 26 } 27 28 char buf[1024]; 29 struct sockaddr_in client; 30 while(1) 31 { 32 socklen_t len=sizeof(client); 33 ssize_t s=recvfrom(sock,buf,sizeof(buf)-1,0,\ 34 (struct sockaddr*)&client,&len); 35 if(s>0) 36 { 37 buf[s]=0; 38 printf("[%s:%d]:&s\n",inet_ntoa(client.sin_addr),\ 39 ntohs(client.sin_port),buf); 40 sendto(sock,buf,strlen(buf),0,\ 41 (struct sockaddr*)&client,sizeof(client)); 42 } 43 } 44 45 }
转载请注明原文地址: https://www.6miu.com/read-2627203.html

最新回复(0)