0
点赞
收藏
分享

微信扫一扫

基于UDP/TCP的 c/s 通信模型

49路末班车 2024-08-27 阅读 31

基于UDP c/s通信模型

  • 客户端(socket;sendto ...)  
  • 服务器端  ---把自己的地址公布出去 (socket;bind //绑定; recvfrom ...)

1.recvfrom函数:

返回值:成功:返回接收到的字节数; 失败:-1。 

struct sockaddr_in srcaddr;
socklen_t addrlen = sizeof(srcaddr);

char buf[1024];
   
while(1)
{
    recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr *)&srcaddr,&addrlen);
        
    printf("IP = %s\n",inet_ntoa(srcaddr.sin_addr));
    printf("post = %d\n",ntohs(srcaddr.sin_port));
    printf("buf = %s\n",buf);
}

2.bind函数:

        (1)功能:如果该函数在服务器端调用,则表示将参数1相关的文件描述符文件与参数2 指定的接口地址关联,用于从该接口接受数据。如果该函数在客户端调用,则表示要将数据从参数1所在的描述符中取出并从参数2所在的接口设备上发送出去。

        注意:如果是客户端,则该函数可以省略,由默认接口发送数据。
        (2)参数:sockfd之前通过socket函数创建的文件描述符,套接字id; my_addr 是物理接口的结构体指针。表示该接口的信息。  

struct sockaddr      通用地址结构 --- ip + 端口 
{
    u_short sa_family;  地址族
    char sa_data[14];   地址信息
};


转换成网络地址结构如下:
struct sockaddr_in    ///网络地址结构
{
    u_short           sin_family; //地址族
    u_short           sin_port;   //地址端口
    struct in_addr  sin_addr;   //地址IP  //"192.168.1.123"
    char               sin_zero[8]; //占位
};
 

in_addr_t  === unsigned int 
struct in_addr
{
    in_addr_t s_addr;
}
          

练习:

           任务1 从键盘获得数据发给服务器  --fgets
           任务2 从服务器不断获取数据打印  --recvfrom 

1.客户端:
int c_fd = 0;
void child_handler(int signo)
{

	close(c_fd);
    printf("child--exit--\n");
	exit(0);

}

void father_handler(int signo)
{

	close(c_fd);
    printf("father--exit--\n");
	exit(0);
}

int main(int argc, const char *argv[])
{
	//1.socket 创建通信的一端 
	int fd = socket(AF_INET,SOCK_DGRAM,0);

	if (fd < 0)
	{
		perror("socket fail");
		return -1;
	}
	
	printf("fd = %d\n",fd);

	struct sockaddr_in seraddr;
	seraddr.sin_family = AF_INET;
	seraddr.sin_port = htons(50000);
	seraddr.sin_addr.s_addr = inet_addr("192.168.1.135");

	char buf[1024] = {0};

	//区分任务 
	pid_t pid = fork();

	if (pid < 0)
	{
		perror("fork fail");
		return -1;
	}

	if (pid > 0)
	{
		signal(SIGCHLD,father_handler);
		c_fd = fd;
		while (1)
		{
			printf(">");
			fgets(buf,sizeof(buf),stdin);
			int ret = sendto(fd,buf,strlen(buf)+1,0,(const struct sockaddr *)&seraddr,sizeof(seraddr));
			printf("ret = %d\n",ret);

			if (strncmp(buf,"quit",4) == 0)
			{
				kill(pid,SIGUSR1);
				wait(NULL);
				close(fd);
				exit(0);
			}
		}
		
	}else if (pid == 0) 
	{
		c_fd = fd;
		signal(SIGUSR1,child_handler);
		while (1)
		{
			recvfrom(fd,buf,sizeof(buf),0,NULL,NULL);
			printf("buf = %s\n",buf);

			if (strncmp(buf,"quit",4) == 0)
			{
				close(fd);
				exit(0);
			}
		}
	}
		
	//close(fd); 
	return 0;
}
2.服务器端:       
int c_fd = 0;
void child_handler(int signo)
{

	close(c_fd);
    printf("child--exit--\n");
	exit(0);

}

void father_handler(int signo)
{

	close(c_fd);
    printf("father--exit--\n");
	exit(0);
}

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

	//1.socket 创建通信的一端 
	int fd = socket(AF_INET,SOCK_DGRAM,0);

	if (fd < 0)
	{
		perror("socket fail");
		return -1;
	}	

	struct sockaddr_in seraddr;
	seraddr.sin_family = AF_INET;
	seraddr.sin_port = htons(50000);
	seraddr.sin_addr.s_addr = inet_addr("192.168.1.135");
	//2.bind
	if (bind(fd,(struct sockaddr *)&seraddr,sizeof(seraddr)) < 0)
	{
		perror("bind fail");
		return -1;
	}

	struct sockaddr_in srcaddr;
	socklen_t addrlen = sizeof(srcaddr);
	char buf[1024];
	//3.接收数据
	recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr*)&srcaddr,&addrlen);
	printf("--------------------\n");
	printf("IP   = %s\n",inet_ntoa(srcaddr.sin_addr));
	printf("post = %d\n",ntohs(srcaddr.sin_port));
	printf("buf = %s\n",buf);
	printf("--------------------\n");

	pid_t pid = fork();

	if (pid < 0)
	{
		perror("fork fail");
		return -1;
	}

	if (pid > 0)
	{
		signal(SIGCHLD,father_handler);
        c_fd = fd;
		while (1)
		{
			//3.接收数据
			recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr*)&srcaddr,&addrlen);
			printf("--------------------\n");
			printf("IP   = %s\n",inet_ntoa(srcaddr.sin_addr));
			printf("post = %d\n",ntohs(srcaddr.sin_port));
			printf("buf = %s\n",buf);
			printf("--------------------\n");
			
			if (strncmp(buf,"quit",4) == 0)
			{
				kill(pid,SIGUSR1);
				wait(NULL);
				close(fd);
				exit(0);
			}
		}

	}else if (pid == 0)
	{
		signal(SIGUSR1,child_handler);
		while (1)
		{
			printf(">");
			fgets(buf,sizeof(buf),stdin);
			sendto(fd,buf,strlen(buf) + 1, 0, (const struct sockaddr*)&srcaddr,sizeof(srcaddr));
			if (strncmp(buf,"quit",4) == 0)
			{
				close(fd);
				exit(0);
			}
		}
	}	
	
	return 0;
}

基于TCP c/s通信模型

tcp 客户端:

(1)建立连接:

  • socket //买了一部手机;
  • bind //可选   //插上sim卡;
  • connect    //拨打电话 ....

(2)通信过程:(read;write;close) 

connect函数:

        (1)功能:该函数固定有客户端使用,表示从当前主机向目标主机发起链接请求。
        (2)参数:sockfd:本地socket创建的套接子id;addr:程目标主机的地址信息;

                        addrlen: 参数2的长度。

        (3)返回值:成功 0;失败 -1;

int main(int argc, const char *argv[])
{
	int fd = socket(AF_INET,SOCK_STREAM,0);

	if (fd < 0)
		handle_error("socket fail");	


	struct sockaddr_in seraddr;
	seraddr.sin_family = AF_INET;
	seraddr.sin_port = htons(50000);
	seraddr.sin_addr.s_addr = inet_addr("192.168.1.135");

	if (connect(fd,(const struct sockaddr*)&seraddr,sizeof(seraddr)) < 0)
		handle_error("connect fail");

	
	return 0;
}

tcp服务器:

(1)建立连接 

  • socket  //买了一部手机 
  • bind    //插上sim卡 
  • listen  //监听 客户端的连接请求 
  • accept  //接听 ---这一步完成之后 连接就建立好了,之后就可以收发数据  

(2)通信过程 (read;write;close)      

listen函数:
accept函数:
int main(int argc, const char *argv[])
{
	int listen_fd = socket(AF_INET,SOCK_STREAM,0);

	if (listen_fd < 0)
		handle_error("socket fail");	


	struct sockaddr_in seraddr;
	seraddr.sin_family = AF_INET;
	seraddr.sin_port = htons(50000);
	seraddr.sin_addr.s_addr = inet_addr("192.168.1.135");

	if (bind(listen_fd,(const struct sockaddr*)&seraddr,sizeof(seraddr)) < 0)
		handle_error("bind fail");


	if (listen(listen_fd,5) < 0)
		handle_error("listen fail");


	int connfd = accept(listen_fd,NULL,NULL);

	if (connfd < 0)
		handle_error("accept fail");

	printf("connfd = %d\n",connfd);

	return 0;
}
举报

相关推荐

0 条评论