IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 5.linux_socket网络编程 -> 正文阅读

[系统运维]5.linux_socket网络编程

目录

一、理论

二、编程实战


一、理论

1. 网络编程

前面学习的管道,消息队列,共享内存,信号,信号量,都依耐于linux内核,无法实现多机通讯,所以要学习网络编程,实现服务器和客户端之间的通讯。

地址:IP地址

???????????端口号:ftp服务/http服务/socket服务

数据:协议(http、tcp、udp)

socket套接字:tcp:面向连接,A打电话B,连接可靠,传指令

? ? ? ? ? ? ? ? ? ? ? ? udp:面向报文,A发短信B,连接不可靠,视频,数据量大

tcp与udp对比:

tcp:面向连接,连接可靠,传指令,点到点,首部开销20个字节,全双工,可靠通信

udp:面向报文,连接不可靠,传视频,一对多、多对一、多对多,首付开销8个字节,不可靠通信

2. 字节序

字节序是指多个字节数据在计算机内存中存储或者网络传输时各字节的存储顺序。

小端字节序(little endian):将低序字节存储在起始地址

大端字节序(big endian):将高序字节存储在起始地址

3. socket是一种独立于协议的网络编程接口,即套接字,是一个抽象套,应用程序可以通过它发送或接收数据,可对其像文件一样打开,读写和关闭等操作,套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信,网络套接字是IP地址与端口的组合,为了满足不同的通信程序,对通信质量和性能的要求,一般的网络系统提供了三种不同类型的套接字,以供用户在设计网络应用程序时,根据不同的要求来选择,为流式套接字、数据套接字、原始套接字。

socket接口是tcp/ip网络的api

二、编程实战

server.c

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>

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

	//int socket(int domain, int type, int protocol);
	int s_fd;
	int c_fd;
	int n_read;
	char readBuf[128];

	char *msg = "I get your connect";
	struct sockaddr_in s_addr;
	struct sockaddr_in c_addr;

	memset(&s_addr,0,sizeof(struct sockaddr_in));	
	memset(&c_addr,0,sizeof(struct sockaddr_in));	

	//1. socket
	//s_fd = socket(AF_LOCAL,SOCK_STREAM,0);	
	s_fd = socket(AF_INET,SOCK_STREAM,0);	
	if(s_fd == -1){
		perror("socket");
		exit(-1);
	}

	s_addr.sin_family = AF_INET;
	s_addr.sin_port = htons(atoi(argv[2]));
	inet_aton(argv[1],&s_addr.sin_addr);
	//inet_aton("127.0.0.1",&s_addr.sin_addr);

	//2. bind
	bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));

	//3. listen
	listen(s_fd,10);

	//4. accept
	int clen = sizeof(struct sockaddr_in);	
	while(1){	 

		c_fd = accept(s_fd, (struct sockaddr *)&c_addr, &clen);
		if(c_fd == -1){
			perror("accept");
		}
		//printf("contend");

		printf("get connect: %s\n", inet_ntoa(c_addr.sin_addr));

		if(fork() == 0){
			//5. read
			n_read = read(c_fd,readBuf,128);
			if(n_read == -1){
				perror("read");
			}else{
				printf("get message: %d,%s\n",n_read,readBuf);
			}
			//6. write
			write(c_fd,msg,strlen(msg));
			break;
		}
	}
	return 0;

}

client.c

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>

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

	//int socket(int domain, int type, int protocol);
	int c_fd;
	int n_read;
	char readBuf[128];

	char *msg = "msg from client";
	struct sockaddr_in c_addr;
	
	memset(&c_addr,0,sizeof(struct sockaddr_in));	

	//1. socket
//	s_fd = socket(AF_LOCAL,SOCK_STREAM,0);	
	c_fd = socket(AF_INET,SOCK_STREAM,0);	
	if(c_fd == -1){
		perror("socket");
		exit(-1);
	}
	
	c_addr.sin_family = AF_INET;
	c_addr.sin_port = htons(atoi(argv[2]));
	inet_aton(argv[1],&c_addr.sin_addr);
	//inet_aton("127.0.0.1",&s_addr.sin_addr);
	
	//2. connect
	if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1 ){
		//perror("connect have cuo wu\n");
		perror("connect \n");
		exit(-1);
	}
	
	//printf("contend");
	
	printf("get connect: %s\n",inet_ntoa(c_addr.sin_addr));
	//3. send
	write(c_fd,msg,strlen(msg));
	
	//4. read
	n_read = read(c_fd,readBuf,128);
	if(n_read == -1){
		perror("read");
	}else{
		printf("get message from server: %d,%s\n",n_read,readBuf);
	}
	
	return 0;

}

CLC@Embed_Learn:~/socket$ gcc server.c -o server

CLC@Embed_Learn:~/socket$ gcc client.c -o client
?

CLC@Embed_Learn:~/socket$ ./server 127.0.0.1 8888
get connect: 127.0.0.1
get message: 15,msg from client
get connect: 127.0.0.1
get message: 15,msg from client

......没有退出
?

CLC@Embed_Learn:~/socket$ ./client 127.0.0.1 8888
get connect: 127.0.0.1
get message from server: 18,I get your connect
CLC@Embed_Learn:~/socket$ ./client 127.0.0.1 8888
get connect: 127.0.0.1
get message from server: 18,I get your connect
CLC@Embed_Learn:~/socket$?? 退出

服务端,在bind()函数中设置好IP号和端口号,先使用监听listen()函数,在使用连接accept()函数,read()函数读客户端的数据,并显示出来,write()函数给客户端返回一个指令状态。服务端不会退出,有一个while()函数,还使用fork()函数,客户端一运行服务端就起来了。

客户端,先使用write()函数,后使用read()函数,与服务端的read和write刚好一一对应起来。我写你读,我读你写。

双方可以实现通信


server1.c

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>

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

	//int socket(int domain, int type, int protocol);
	int s_fd;
	int c_fd;
	int n_read;
	char readBuf[128];

	char msg[128] = {0};
	//	char *msg = "I get your connect";
	struct sockaddr_in s_addr;
	struct sockaddr_in c_addr;

	if(argc != 3){
		printf("param is not good\n");
		exit(-1);
	}

	memset(&s_addr,0,sizeof(struct sockaddr_in));	
	memset(&c_addr,0,sizeof(struct sockaddr_in));	

	//1. socket
	//	s_fd = socket(AF_LOCAL,SOCK_STREAM,0);	
	s_fd = socket(AF_INET,SOCK_STREAM,0);	
	if(s_fd == -1){
		perror("socket");
		exit(-1);
	}

	s_addr.sin_family = AF_INET;
	s_addr.sin_port = htons(atoi(argv[2]));
	inet_aton(argv[1],&s_addr.sin_addr);
	//inet_aton("127.0.0.1",&s_addr.sin_addr);

	//2. bind
	bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));

	//3. listen
	listen(s_fd,10);

	//4. accept
	int clen = sizeof(struct sockaddr_in);	
	while(1){	 

		c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen);
		if(c_fd == -1){
			perror("accept");
		}
		//printf("contend");

		printf("get connect: %s\n",inet_ntoa(c_addr.sin_addr));

//数据有到来时,创建一个上面的子进程去操作,子进程同时执行两个while(1),按照以前的经验,想要执行两个while(1),要么用线程,要么创建一个下面的子进程,
//两个while(1)同时跑,上面的子进程对接的是一个客户端,它既能不断的来检测,往套接字上面发送数据,也能读取套接字上面的数据。
		if(fork() == 0){

			if(fork() == 0){
				while(1){
					memset(msg,0,sizeof(msg));
					printf("input: ");
					gets(msg);
					//6. write
					write(c_fd,msg,strlen(msg));
				}
			}
			while(1){
				memset(readBuf,0,sizeof(readBuf));
				//5. read
				n_read = read(c_fd,readBuf,128);
				if(n_read == -1){
					perror("read");
				}else{
					printf("get message: %d,%s\n",n_read,readBuf);
				}
			}
			break;
		}
	}
	return 0;

}

?client1.c

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>

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

	//int socket(int domain, int type, int protocol);
	int c_fd;
	int n_read;
	char readBuf[128];

	//	char *msg = "msg from client";
	char msg[128] = {0};
	struct sockaddr_in c_addr;

	memset(&c_addr,0,sizeof(struct sockaddr_in));	

	if(argc != 3){
		printf("param is not good\n");
		exit(-1);
	}

	//1. socket
	//	s_fd = socket(AF_LOCAL,SOCK_STREAM,0);	
	c_fd = socket(AF_INET,SOCK_STREAM,0);	
	if(c_fd == -1){
		perror("socket");
		exit(-1);
	}

	c_addr.sin_family = AF_INET;
	c_addr.sin_port = htons(atoi(argv[2]));
	inet_aton(argv[1],&c_addr.sin_addr);
	//inet_aton("127.0.0.1",&s_addr.sin_addr);

	//2. connect
	if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1 ){
		//perror("connect have cuo wu\n");
		perror("connect \n");
		exit(-1);
	}
	while(1){//客户端:while(1)中要执行两个while(1),要么用线程,要么用创建一个子进程,这么创建了一个子进程来完成这个操作
		if(fork() == 0){
			while(1){
				memset(msg,0,sizeof(msg));
				printf("input: ");
				gets(msg);
				//write
				write(c_fd,msg,strlen(msg));
			}
		}
		while(1){
			memset(readBuf,0,sizeof(readBuf));
			//4. read
			n_read = read(c_fd,readBuf,128);
			if(n_read == -1){
				perror("read");
			}else{
				printf("get message from server: %d,%s\n",n_read,readBuf);
			}
		}
	}

	//printf("contend");

	//printf("get connect: %s\n",inet_ntoa(c_addr.sin_addr));
	//3. send
	write(c_fd,msg,strlen(msg));

	return 0;
}

CLC@Embed_Learn:~/socket$ gcc server1.c -o server1
CLC@Embed_Learn:~/socket$ gc client1.c -o client1
?

CLC@Embed_Learn:~/socket$ ./server1 127.0.0.1 8888
get connect: 127.0.0.1
input: get message: 12,nihao client
nihao server
input: hello server
input: get message: 12,hello client?

CLC@Embed_Learn:~/socket$ ./client1 127.0.0.1 8888
input: nihao,client
input: get message from server: 12,nihao,server
get message from server: 12,hello server
hello client

可以实现双方互相聊天,那么可以实现多人聊天吗?请看server2.c


?server2.c

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>

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

	//int socket(int domain, int type, int protocol);
	int s_fd;
	int c_fd;
	int n_read;
	char readBuf[128];
	
	int mark = 0;
	char msg[128] = {0};
	//	char *msg = "I get your connect";
	struct sockaddr_in s_addr;
	struct sockaddr_in c_addr;

	if(argc != 3){
		printf("param is not good\n");
		exit(-1);
	}

	memset(&s_addr,0,sizeof(struct sockaddr_in));	
	memset(&c_addr,0,sizeof(struct sockaddr_in));	

	//1. socket
	//	s_fd = socket(AF_LOCAL,SOCK_STREAM,0);	
	s_fd = socket(AF_INET,SOCK_STREAM,0);	
	if(s_fd == -1){
		perror("socket");
		exit(-1);
	}

	s_addr.sin_family = AF_INET;
	s_addr.sin_port = htons(atoi(argv[2]));
	inet_aton(argv[1],&s_addr.sin_addr);
	//inet_aton("127.0.0.1",&s_addr.sin_addr);

	//2. bind
	bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));

	//3. listen
	listen(s_fd,10);

	//4. accept
	int clen = sizeof(struct sockaddr_in);	
	while(1){	 

		c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen);
		if(c_fd == -1){
			perror("accept");
		}
		//printf("contend");

		mark++;

		printf("get connect: %s\n",inet_ntoa(c_addr.sin_addr));

		if(fork() == 0){

			if(fork() == 0){
				while(1){
					sprintf(msg,"welcom No.%d client",mark);
					//6. write
					write(c_fd,msg,strlen(msg));
					sleep(3);
				}
			}
			while(1){
				memset(readBuf,0,sizeof(readBuf));
				//5. read
				n_read = read(c_fd,readBuf,128);
				if(n_read == -1){
					perror("read");
				}else{
					printf("get message: %d,%s\n",n_read,readBuf);
				}
			}
			break;
		}
	}
	return 0;
}

client1.c

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>

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

	//int socket(int domain, int type, int protocol);
	int c_fd;
	int n_read;
	char readBuf[128];

	//	char *msg = "msg from client";
	char msg[128] = {0};
	struct sockaddr_in c_addr;

	memset(&c_addr,0,sizeof(struct sockaddr_in));	

	if(argc != 3){
		printf("param is not good\n");
		exit(-1);
	}

	//1. socket
	//	s_fd = socket(AF_LOCAL,SOCK_STREAM,0);	
	c_fd = socket(AF_INET,SOCK_STREAM,0);	
	if(c_fd == -1){
		perror("socket");
		exit(-1);
	}

	c_addr.sin_family = AF_INET;
	c_addr.sin_port = htons(atoi(argv[2]));
	inet_aton(argv[1],&c_addr.sin_addr);
	//inet_aton("127.0.0.1",&s_addr.sin_addr);

	//2. connect
	if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1 ){
		//perror("connect have cuo wu\n");
		perror("connect \n");
		exit(-1);
	}
	while(1){//客户端:while(1)中要执行两个while(1),要么用线程,要么用创建一个子进程,这么创建了一个子进程来完成这个操作
		if(fork() == 0){
			while(1){
				memset(msg,0,sizeof(msg));
				printf("input: ");
				gets(msg);
				//write
				write(c_fd,msg,strlen(msg));
			}
		}
		while(1){
			memset(readBuf,0,sizeof(readBuf));
			//4. read
			n_read = read(c_fd,readBuf,128);
			if(n_read == -1){
				perror("read");
			}else{
				printf("get message from server: %d,%s\n",n_read,readBuf);
			}
		}
	}

	//printf("contend");

	//printf("get connect: %s\n",inet_ntoa(c_addr.sin_addr));
	//3. send
	write(c_fd,msg,strlen(msg));

	return 0;
}

CLC@Embed_Learn:~/socket$ gcc server2.c -o server2
CLC@Embed_Learn:~/socket$ gcc client1.c -o client1


CLC@Embed_Learn:~/socket$ ./server2 127.0.0.1 8877
get connect: 127.0.0.1
get message: 5,nihao?
get connect: 127.0.0.1

CLC@Embed_Learn:~/socket$ ./client1 127.0.0.1 8877
input: get message from server: 18,welcom No.1 client
get message from server: 18,welcom No.1 client
get message from server: 18,welcom No.1 client
nihao get message from server: 18,welcom No.1 client

input: get message from server: 18,welcom No.1 client
get message from server: 18,welcom No.1 client
get message from server: 18,welcom No.1 client

......


CLC@Embed_Learn:~/socket$ ./client1 127.0.0.1 8877
input: get message from server: 18,welcom No.2 client
get message from server: 18,welcom No.2 client
get message from server: 18,welcom No.2 client
......

1 ?可以多人聊天,但存在竞争关系

2 ?存在资源竞争,所以服务器发送的消息,不能同时给两个客户端发过去,现在让服务端自动给客户端回复消息。
? ??如果我们不获取键盘的输入,每一个客户端发数据上来,自动的回复,客户端就知道连接有没有丢失。服务端都可以收到客户端的请求。

?

?

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-09-24 21:30:38  更:2022-09-24 21:32:58 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 9:28:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码