现在的位置: 首页 > 综合 > 正文

socket编程(2)一对多通信模型

2017年06月18日 ⁄ 综合 ⁄ 共 3814字 ⁄ 字号 评论关闭

一对多模型
TCP的编程步骤:
服务端:
1、socket()获得一个sockfd。注意第二个参数必须SOCK_STREAM.
2、准备通信地址(必须服务器的)
3、bind()绑定。(开放了端口,允许客户端连接)
4、监听客户端 listen()函数
5、等待客户端的连接 accept(),返回用于交互的socket描述符
6、使用第5步返回sockt描述符,进行读写通信。
7、关闭sockfd。
客户端的代码与一对一的一样。注意第二个参数必须SOCK_STREAM.
TCP一对多模型,有两类描述符:

第一步的描述符不再参与信息交互,只是等待客户端的连接(accept),accept()在客户端连接上来后,会返回一个新的描述符,用于读写通信。

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

int main(){
	int sockfd = socket(AF_INET,SOCK_STREAM,0);
	if (sockfd == -1){
		perror("socket"),exit(-1);
	}
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(2222);
	addr.sin_addr.s_addr = inet_addr("192.168.66.11");
	int res = bind(sockfd,(struct sockaddr*)&addr,
			sizeof(addr));
	if (res == -1){
		perror("bind"),exit(-1);
	}
	printf("bind ok\n");
	listen(sockfd,100);//监听
	struct sockaddr_in client;
	socklen_t len = sizeof(client);
	int fd = accept(sockfd,(struct sockaddr*)&client,&len);
	char *from = inet_ntoa(client.sin_addr);//十六进制转点分十进制
	printf("%s连接成功\n",from);
	char buf[100] = {};
	res = read(fd,buf,sizeof(buf));
	printf("接受了%d字节,内容:%s",res,buf);
	write(fd,"welcome",7);
	close(fd);
	close(sockfd);
	return 0;
}

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

int main(){
	int sockfd = socket(AF_INET,SOCK_STREAM,0);
	if (sockfd == -1){
		perror("socket"),exit(-1);
	}
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(2222);//连接端口
	addr.sin_addr.s_addr = inet_addr("192.168.66.11");//都是服务器的,改成连接IP
	int res = connect(sockfd,(struct sockaddr*)&addr,
			sizeof(addr));
	if (res == -1){
		perror("connect"),exit(-1);
	}
	printf("连接成功\n");
	write(sockfd,"hello",5);
	char buf[100] = {};
	res = read(sockfd,buf,sizeof(buf));
	printf("读到了%d字节,内容:%s\n",res,buf);
	close(sockfd);
	return 0;
}

练习:
1、在客户端加上输入功能,允许发送不同的信息,并且客户端和服务器端代码要支持多次输入和输出(读写上加循环),输入bye退出。

客户端发送的内容改为输入,服务器发回给客户端的内容改成客户端的输入。
2、可以考虑在服务器端启动多进程fork(),支持多个客户端的并行。

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

int sockfd;
void fa(int signo){
	printf("服务器正在关闭\n");
	sleep(1);
	close(sockfd);
	exit(0);
}
int main(){
	printf("ctrl+c退出服务器\n");
	signal(SIGINT,fa);
	int sockfd = socket(AF_INET,SOCK_STREAM,0);
	if (sockfd == -1){
		perror("socket"),exit(-1);
	}
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(2222);
	addr.sin_addr.s_addr = inet_addr("192.168.66.11");

	int reuseaddr = 1;//解决地址已被占用问题
	setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,
			&reuseaddr,sizeof(reuseaddr));

	int res = bind(sockfd,(struct sockaddr*)&addr,
			sizeof(addr));
	if (res == -1){
		perror("bind"),exit(-1);
	}
	printf("bind ok\n");
	listen(sockfd,100);//监听
	while (1){
		struct sockaddr_in client;
		socklen_t len = sizeof(client);
		int fd = accept(sockfd,(struct sockaddr*)&client,
				&len);//阻塞函数
		char *from = inet_ntoa(client.sin_addr);
		printf("%s连接成功\n",from);
		pid_t pid = fork();
		if (pid == 0){
		char buf[100] = {};
		while (1){
			res = read(fd,buf,sizeof(buf));
			printf("接受了%d字节,内容:%s\n",res,buf);
			if (res <= 0){//包括0和-1
				break;
			}
			if (strcmp(buf,"bye") == 0){
				break;
			}
			write(fd,buf,strlen(buf));
			memset(buf,0,sizeof(buf));
		}
		close(fd);
		exit(0);
		}
	close(fd);
	}
}

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

int main(){
	int sockfd = socket(AF_INET,SOCK_STREAM,0);
	if (sockfd == -1){
		perror("socket"),exit(-1);
	}
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(2222);//连接端口
	addr.sin_addr.s_addr = inet_addr("192.168.66.11");//都是服务器的,改成连接IP
	int res = connect(sockfd,(struct sockaddr*)&addr,sizeof(addr));
	if (res == -1){
		perror("connect"),exit(-1);
	}
	printf("连接成功\n");

	char buf[100] = {};
	while (1){
		memset(buf,0,sizeof(buf));//buf清0
		printf("请输入要说的话\n");
		scanf("%s",buf);
		write(sockfd,buf,strlen(buf));
		if (strcmp(buf,"bye") == 0){//退出的合适位置
			break;
		}
		memset(buf,0,sizeof(buf));//buf清0
		res = read(sockfd,buf,sizeof(buf));
		printf("读到了%d字节,内容:%s\n",res,buf);
	}

	close(sockfd);
	return 0;
}

抱歉!评论已关闭.