9 linux socket 网络编程基础

网络

什么是网络:多个主机连在一起
什么是主机:交换机,基站,路由器,电脑,手机……(只要是能连接到网络的计算机都是主机)
如何连接·:无线电,光,电……
网络分层:

OIS参考模型5层参考模型
应用层
表示层应用层
会话层
传输层传输层
网络层网络层
数据链路层数据链路层
物理层物理层

IP:区分网络中不同主机,本质是个整数,IPV4是个四字节整数
192.168.1.132 数点格式
网口:192.168.1.0 作为网关
子网掩码(255.255.255.0): 前面三段用来确定路由,最后一段用来确定主机,

子网掩码&ip==前面三个字节
子网掩码按位取反&ip==最后一个字节

端口:同一个主机上有多个端口,在网络通信的时候每一个进程占用唯一一个端口,浏览器占用80端口,使用时通常从小到大使用,个人所写应用程序一般使用5000以上的端口号,一共有65536个端口,建议使用一万左右网络服务器一般是unix系统,大小端系统有区别,代码中使用端口号需要从小端转变成大端

#include<stdio.h>
union u{
	char c[4];
	int n;
}
int main(){
	//类型决定存储方式和占用大小
	//比如 int 4字节(有4个地址) 个人电脑一般为x86架构 , 网络的一般为arm架构 或者是其他架构
	//x86 为小端系统 :高位数据在高地址上,低位数据在低地址上
	//大段系统:高位数据在低地址上,低位数据在高地址上
	//网络服务器都是大端系统
	union uu;
	uu.n=0x11223344;
	printf("%x %x %x %x \n",uu.c[0],uu.c[1],uu.c[2],uu.c[3]);
	return 0;
}

打印结果为 :44 33 22 11


TCP协议

TCP协议:

编程模型
服务器客户端
1.创建socket 函数1.创建socket
2.确定服务器协议地址簇 struct sockaddr_in 结构2.获取服务器协议地址簇 struct sockaddr_in 结构
3.绑定 bind函数
4.监听listen函数
5.接收连接accept函数来接受客户端的信息; accept函数是个阻塞函数3.连接服务器connect函数
6.通信 接收信息 revc函数4.通信 send函数
7.断开连接 close5.断开连接 close


服务器函数

socket函数:

在这里插入图片描述通信媒介:
TCP使用:SOCK_STREAM;
UPD使用:SOCK_DGRAM;



bind绑定函数:
第一个参数为:socket函数返回值
第二个参数为:协议地址簇地址
第三个参数为:协议地址簇长度
在这里插入图片描述struct sockaddr {
unsigned short sa_family; /* 地址族, AF_xxx /
char sa_data[14]; /
14字节的协议地址*/
};
以上为通用socket地址簇

Internet socket地址簇:用下面的结构,二者可以进行类型转换
struct sockaddr_in {
short int sin_family; /* 地址族 /
unsigned short int sin_port; /
端口号 /
struct in_addr sin_addr; /
Internet地址 /
unsigned char sin_zero[8]; /
与struct sockaddr一样的长度 ,可以不使用*/
};


htons 函数
htons是将整型变量从主机字节顺序转变成网络字节顺序, 就是整数在地址空间存储方式变为高位字节存放在内存的低地址处。
在这里插入图片描述

atoi函数:把字符串转换成整型数.

inet_addr函数:inet_addr()作用是将一个IP字符串转化为一个网络字节序的整数值

inet_aton():函数是一个改进的方法来将一个字符串IP地址转换为一个32位的网络序列IP地址。


inet_ntoa:返回点分十进制的字符串在静态内存中的指针。

示例:
在这里插入图片描述

listen函数:
第一个参数:socket返回值
第二个参数:侦听队列的长度
在这里插入图片描述

accept函数:在这里插入图片描述

recv函数:
在这里插入图片描述

示例

服务器:

#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<signal.h>
int sockFd,ClientSocket;//服务器 客户端
void hand(){
	//7.断开连接
	close(sockFd);
	close(ClientSocket);
	printf("bye\n");
	exit(0);
}

int main(int argc,char* argv[]){
	if(argc!=3)printf("请输入IP地址和端口号\n"),exit(0);
	printf("IP:%s     port:%d\n",argv[1],atoi(argv[2]));
	//7.断开连接
	signal(2,hand);//SIGINT        终端中断   2
	//1.创建socket
	sockFd=socket(AF_INET,SOCK_STREAM,0);
	if(-1==sockFd)printf("创建Socket失败:%m\n"),exit(-1);
	printf("创建socket成功\n");
	
	/*
	atoi函数:把字符串转换成整型数.
	inet_addr函数:inet_addr()作用是将一个IP字符串转化为一个网络字节序的整数值
	inet_aton():函数是一个改进的方法来将一个字符串IP地址转换为一个32位的网络序列IP址。 
	inet_ntoa:返回点分十进制的字符串在静态内存中的指针。
	htons是将整型变量从主机字节顺序转变成网络字节顺序, 就是整数在地址空间存储方式变为高位字节存放在内存的低地址处。
	*/

	//2.创建服务器协议地址簇
	struct sockaddr_in addr={0};//in为linux ,un为unix
	addr.sin_family=AF_INET;//协议类型 和socket第一个参数一样
	addr.sin_addr.s_addr=inet_addr(argv[1]);//sin_addr.s_addr获取Internet地址 
	addr.sin_port=htons(atoi(argv[2]));//整形小段转成大端
	
	//3.绑定
	int r=bind(sockFd,(struct sockaddr *)&addr,sizeof(addr));
	if(r==-1)printf("绑定失败:%m\n"),close(sockFd),exit(-2);
	printf("绑定成功\n");
	
	//4.监听
	int l=listen(sockFd,10);
	if(l==-1)printf("监听失败:%m\n"),close(sockFd),exit(-2);
	printf("监听成功\n");
	
	//5.接收客户端连接
	struct sockaddr_in ClientAddr={0};//客户端协议地址簇
	int len=sizeof(ClientAddr);
	ClientSocket=accept(sockFd,(struct sockaddr *)&ClientAddr,&len);
	if(-1==ClientSocket)printf("服务器崩溃:%m\n"),close(sockFd),exit(-2);
	printf("有客户端连接服务器:%s\n",inet_ntoa(ClientAddr.sin_addr));//将IP地址转换为它所对应的点分十进制串
	//inet_ntoa:返回点分十进制的字符串在静态内存中的指针。
	
	//6.通信
	char buff[256];
	while(1)
	{
		int r=revc(ClientSocket,buff,255,0);
		if(r>0){
			buff[r]=0;//添加结束字符
			printf(">>%s\n",buff);
		}
	}
	
	//7.断开连接
	//signal(2,hand);
	return 0;
}


客户端函数:

connect 函数与bind函数对应:
在这里插入图片描述

send函数与recv函数对应:
在这里插入图片描述

客户端:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<signal.h>
#include<string.h>

int ClientSocket;//客户端
void hand(){
	//5.断开连接
	close(ClientSocket);
	printf("bye\n");
	exit(0);
}

int main(int argc,char* argv[]){
	if(argc!=3)printf("请输入IP地址和端口号\n"),exit(0);
	printf("IP:%s     port:%d\n",argv[1],atoi(argv[2]));
	//5.断开连接
	signal(2,hand);
	
	//1.创建socket
	ClientSocket=socket(AF_INET,SOCK_STREAM,0);
	if(-1==ClientSocket)printf("创建Socket失败:%m\n"),exit(-1);
	printf("创建socket成功\n");

    /*
	atoi函数:把字符串转换成整型数.
	inet_addr函数:inet_addr()作用是将一个IP字符串转化为一个网络字节序的整数值
	inet_aton():函数是一个改进的方法来将一个字符串IP地址转换为一个32位的网络序列IP址。 
	inet_ntoa:返回点分十进制的字符串在静态内存中的指针。
	htons是将整型变量从主机字节顺序转变成网络字节顺序, 就是整数在地址空间存储方式变为高位字节存放在内存的低地址处。
	*/
	

	//2.获取服务器协议地址簇
	struct sockaddr_in addr={0};//in为linux ,un为unix
	addr.sin_family=AF_INET;//协议类型 和socket第一个参数一样
	addr.sin_addr.s_addr=inet_addr(argv[1]);//sin_addr.s_addr获取Internet地址 
	addr.sin_port=htons(atoi(argv[2]));//整形小段转成大端
	
	
	//3.连接服务器
	int r=connect(ClientSocket,(struct sockaddr *)&addr,sizeof(addr));
	if(r==-1)printf("连接服务器失败:%m\n"),close(ClientSocket),exit(-2);
	printf("连接服务器成功\n");
	
	//4.通信
	char buff[256];
	while(1)
	{
		printf("请输入\n");
		scanf("%s",buff);
		send(ClientSocket,buff,strlen(buff),0);
	}
	
	

	return 0;
}

ifconfig 命令查看ip端口号
在这里插入图片描述


文件传输

文件传输(在已经建立好连接的情况下去完成):

接收端:服务器发送端:客户端
1. 等待客户端发送1.发送文件名
2.接收文件名并创建文件2.获取并发送文件大小
3.接收文件大小新建文件3.发送文件名和文件大小
4.循环接收并写入数据4. 循环读取并发送
5.接收数据足够,关闭文件5. 发送完毕,关闭

示例

接收端:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<signal.h>
#include<fcntl.h>

int serverSocket,clientSocket;//服务器 客户端

int main(){
	
	//1.创建socket
	serverSocket=socket(AF_INET,SOCK_STREAM,0);
	if(-1==serverSocket)printf("创建Socket失败:%m\n"),exit(-1);
	printf("创建socket成功\n");
	
	//2.创建服务器协议地址簇
	struct sockaddr_in addr={0};//in为linux ,un为unix
	addr.sin_family=AF_INET;//协议类型 和socket第一个参数一样
	addr.sin_addr.s_addr=inet_addr("127.0.0.1");//sin_addr.s_addr获取Internet地址 
	addr.sin_port=htons(atoi(10086));//整形小段转成大端
	
	//3.绑定
	int r=bind(serverSocket,(struct sockaddr *)&addr,sizeof(addr));
	if(r==-1)printf("绑定失败:%m\n"),close(serverSocket),exit(-2);
	printf("绑定成功\n");
	
	//4.监听
	int l=listen(serverSocket,10);
	if(l==-1)printf("监听失败:%m\n"),close(serverSocket),exit(-2);
	printf("监听成功\n");
	
	//5.接收客户端连接
	struct sockaddr_in ClientAddr={0};//客户端协议地址簇
	int len=sizeof(ClientAddr);
	v=accept(serveSocket,(struct sockaddr *)&ClientAddr,&len);
	if(-1==clientSocket)printf("服务器崩溃:%m\n"),close(serverSocket),exit(-2);
	printf("有客户端连接服务器:%s\n",inet_ntoa(ClientAddr.sin_addr));//将IP地址转换为它所对应的点分十进制串
	
	//6.通信
	
	//文件操作
	
	//2.接收文件名
	char buff[256];
	char fileName[256]={0};
	int fileSize;
	int count=0;
	r=recv(clientSocket,fileName,255,0);
	if(r>0)
	{
		printf("接收文件名:%s\n",fileName);
	}
	
	//3.接收文件大小
	r=recv(clientSocket,(char*)&fileSize,4,0);
	if(r==4)
	{
		printf("接收到文件大小:%d\n",fileSize);
	}
	
	//4.循环接收并写入文件
	int fd=fopen(fileName,O_CREAT|O_WRONLY,0666);
	
	while(1){
		r=recv(clientSocket,buff,1024,0);
		if(r>))
		{
			write(fd,buff,r);
			count+=r;
			if(count>=fileSize)break;
		}
	}
	
	//5.关闭文件
	close(fd);
	sleep(1);
	printf("接收完毕");
	close(clientSocket);
	close(serverSocket);
	return 0;
}

发送端:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<signal.h>
#include<string.h>
#include<sys/stat.h>
#include<fcntl.h>

int clientSocket;//客户端

int main(int argc,char* argv[]){

	//1.创建socket
	clientSocket=socket(AF_INET,SOCK_STREAM,0);
	if(-1==clientSocket)printf("创建Socket失败:%m\n"),exit(-1);
	printf("创建socket成功\n");
	
	//2.获取服务器协议地址簇
	struct sockaddr_in addr={0};//in为linux ,un为unix
	addr.sin_family=AF_INET;//协议类型 和socket第一个参数一样
	addr.sin_addr.s_addr=inet_addr("127.0.0.1");//sin_addr.s_addr获取Internet地址 
	addr.sin_port=htons(atoi(10086));//整形小段转成大端
	
	
	//3.连接服务器
	int r=connect(clientSocket,(struct sockaddr *)&addr,sizeof(addr));
	if(r==-1)printf("连接服务器失败:%m\n"),close(clientSocket),exit(-2);
	printf("连接服务器成功\n");
	
	//4.通信
	
	//发送文件操作
	
	//1.发送文件名
	int fd=open(argv[1],O_WRONLY);
	if(fd==-1)printf("打开文件失败:%m\n"),close(clientSocket),exit(-1);
	printf("打开文件成功\n");
	
	//2.获取文件大小
	int fileSize=0;
	strcut stat st={0};
	stat(argv[1],&st);
	printf("文件的大小为:%d\n",st.st_size);
	
	//3.发送文件名和文件大小
	send(clientSocket,argv[1],strlen(argv[1]),0);//发送文件名
	send(clientSocket,(char*)&st.st_size,4,0);//发送文件大小
	
	//4. 循环读取并发送
	char buff[1024];
	while(1)
	{
		r=read(fd,buff,1024);
		if(r>0){
			send(clientSocket,buff,0);
		}else{
			break;
		}
	}
	
	//5. 发送完毕,关闭
	printf("发送完毕");
	close(fd);
	sleep(1);
	close(clientSocket);

	return 0;
}

在这里插入图片描述


UDP协议:

编程模型
服务器客户端
1.创建socket1.创建socket
2.确定服务器地址簇2.获取服务器协议地址簇
3.绑定
4.通信3.通信
5.断开连接5.断开连接

函数:

recvfrom 函数:
在这里插入图片描述

sendto函数:

在这里插入图片描述

示例

服务器:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<signal.h>
int serverSocket;//服务器 

void hand(){
	//5.断开连接
	close(serverSocket);
	printf("bye\n");
	exit(0)
}

int main(int argc,char* argv[]){
	if(argc!=3)printf("请输入IP地址和端口号\n"),exit(0);
	printf("IP:%s     port:%d\n",argv[1],atoi(argv[2]));
	
	//7.断开连接
	signal(2,hand);
	
	//1.创建socket
	serverSocket=socket(AF_INET,SOCK_DGRAM,0);
	if(-1==serverSocket)printf("创建Socket失败:%m\n"),exit(-1);
	printf("创建socket成功\n");
	
	//2.创建服务器协议地址簇
	struct sockaddr_in addr={0};//in为linux ,un为unix
	addr.sin_family=AF_INET;//协议类型 和socket第一个参数一样
	addr.sin_addr.s_addr=inet_addr(argv[1]);//sin_addr.s_addr获取Internet地址 
	addr.sin_port=htons(atoi(argv[2]));//整形小段转成大端
	
	//3.绑定
	int r=bind(serveSocket,(struct sockaddr *)&addr,sizeof(addr));
	if(r==-1)printf("绑定失败:%m\n"),close(serverSocket),exit(-2);
	printf("绑定成功\n");
	
	//4.通信
	char buff[256];
	struct sockaddr_in clientAddr={0};
	int len=sizeof(clientAddr);
	while(1)
	{
		int r=recvfrom(serverSocket,buff,255,0,(struct sockaddr *)&clientAddr,&len);//接收客户端的协议地址簇,像协议地址簇发东西
		if(r>0){
			buff[r]=0;//添加结束字符
			printf(">>%s\n",buff);
			
			sendto(serverSocket,"服务器",
			strlen("服务器"),0,(struct sockaddr *)&clientAddr,sizeof(clientAddr));//发送
		}
	}
	
	return 0;
}

客户端:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<signal.h>
int clientSocket;// 客户端

void hand(){
	//4.断开连接
	close(clientSocket);
	printf("bye\n");
	exit(0);
}

int main(int argc,char* argv[]){
	if(argc!=3)printf("请输入IP地址和端口号\n"),exit(0);
	printf("IP:%s     port:%d\n",argv[1],atoi(argv[2]));
	
	//4.断开连接
	signal(2,hand);
	
	//1.创建socket
	clientSocket=socket(AF_INET,SOCK_DGRAM,0);
	if(-1==clientSocket)printf("创建Socket失败:%m\n"),exit(-1);
	printf("创建socket成功\n");
	
	//2.创建服务器协议地址簇
	struct sockaddr_in addr={0};//in为linux ,un为unix
	addr.sin_family=AF_INET;//协议类型 和socket第一个参数一样
	addr.sin_addr.s_addr=inet_addr(argv[1]);//sin_addr.s_addr获取Internet地址 
	addr.sin_port=htons(atoi(argv[2]));//整形小段转成大端
	
	//3.通信
	char buff[256];
	char temp[256];
	int len=sizeof(addr);
	int r;
	while(1)
	{
		printf("请发送\n");
		scanf("%s",buff);
		sendto(clientSocket,buff,strlen(buff),0,(struct sockaddr *)&addr,sizeof(addr));
		r=recvfrom(clientSocket,temp,255,0,(struct sockaddr *)&addr,&len);
		if(r>)){
			temp[r]=0;
			printf("服务器发来信息%s\n",temp);
			
		}
	}

	return 0;
}

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值