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

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值