C/S模型测试

发布于:2024-06-01 ⋅ 阅读:(160) ⋅ 点赞:(0)

1

1.1代码示例

#include<stdio.h>
#include<stdio.h>

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>

#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>

#include <sys/stat.h>
#include <fcntl.h>
    
#include <unistd.h>

#include <string.h>

int main(void)
{
	int sockfd=0;
	int ret=0;
	struct sockaddr_in seraddr;

	char tmpbuff[4096]={"I need some offers"};
	int cnt=0;
	ssize_t nsize=0;

	/* 1 创建网络套接字 */
	sockfd=socket(AF_INET,SOCK_STREAM,0);
	if(-1==sockfd)
	{
		perror("fail to socket");
		return -1;
	}

	/* 2 初始化网络地址结构体 */
	seraddr.sin_family=AF_INET;
	seraddr.sin_port=htons(50000);
	seraddr.sin_addr.s_addr=inet_addr("192.168.1.123");

	/* 3 发送连接请求 */
	ret=connect(sockfd,(struct sockaddr *)&seraddr,sizeof(seraddr));
	if(-1==ret)
	{
		perror("fail to connect");
		return -1;
	}

	/* 4 客户端与服务器交互 */
	while(1)
	{
#if 0
		/* 4.1 清空发送缓冲区 */
		memset(tmpbuff,0,sizeof(tmpbuff));
		/* 4.2 拼接数据 */
		sprintf(tmpbuff,"client send:### %d",cnt);
		cnt++;

		/* 4.3 发送数据到网络套接字 */
		nsize=send(sockfd,tmpbuff,strlen(tmpbuff),0);
		if(-1==nsize)
		{
			perror("fail to send");
			return -1;
		}
#endif

#if 1
		/* 清空接收缓冲区 */
		memset(tmpbuff,0,sizeof(tmpbuff));
		/* 接收网络套接字数据 */
		nsize=recv(sockfd,tmpbuff,sizeof(tmpbuff),0);
		if(-1==nsize)
		{
			perror("fail to recv");
			return -1;
		}
#endif
		
		/* 显示接收数据 */
		printf("client recv:### %s\n",tmpbuff);
	}

	/* 5 关闭网络套接字 */
	close(sockfd);

	return 0;
}



int main(void)
{
    int sockfd=0;
    struct sockaddr_in seraddr;
    int ret=0; 

    int confd=0;
    char tmpbuff[4096]={0};
    ssize_t nsize=0;

    /* 1 创建网络套接字 */
    sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(-1==sockfd)
    {
        perror("fail to socket");
        return -1;
    }
    
    /* 2 初始化网络地址结构体 */
    seraddr.sin_family=AF_INET;
    seraddr.sin_port=htons(50000);
    seraddr.sin_addr.s_addr=inet_addr("192.168.1.123");

    /* 3 绑定网络套接字 */
    ret=bind(sockfd,(struct sockaddr *)&seraddr,sizeof(seraddr));
    if(-1==ret)
    {
        perror("fail to bind");
        return -1;
    }

    /* 4 监听网络套接字 */
    ret=listen(sockfd,10);
    if(-1==ret)
    {
        perror("fail to listen");
        return -1;
    }

    /* 5 服务器与客户端交互 */
    while(1)
    {
        /* 5.1 创建通信套接字-阻塞等待网络套接字连接请求*/
        confd=accept(sockfd,NULL,NULL);
        if(-1==confd)
        {
            perror("fail to accept");
            return -1;
        }

#if 0
        /* 5.2 清空接收缓冲区 */
        memset(tmpbuff,0,sizeof(tmpbuff));
        /* 5.3 接收通信套接字数据-并做接收完成处理 */
        nsize=recv(confd,tmpbuff,sizeof(tmpbuff),0);
        if(-1==nsize)
        {
            perror("fail to recv");
            return -1;
        }
        else if(0==nsize)
        {
            return 0;
        }
#endif
        
        /* 5.2 清空发送缓冲区 */
        memset(tmpbuff,0,sizeof(tmpbuff));
        /* 5.4 拼接 */
        sprintf(tmpbuff,"server send:### %s",tmpbuff);
        /* 5.5 发送 */
        nsize=send(confd,tmpbuff,strlen(tmpbuff),0);
        if(-1==nsize)
        {
            perror("fail to send");
            return -1;
        }
    }

    /* 6 关闭通信套接字 */
    close(confd);
    /* 7 关闭网络套接字 */
    close(sockfd);

    return 0;
}

1.2运行结果

(1)运行服务器
(2)运行客户端

现象如下:
	客户端发生阻塞

在这里插入图片描述

(1)关闭服务器:
	客户端不阻塞-说明recv函数为非阻塞状态

在这里插入图片描述

总结:
(1)如果将服务器accept函数放在while循环内部:同时运行客户端与服务器,可以发现服务器可以与多个客户端建立连接(解决的问题-服务器并发访问)。
(2)但是只能进行一次数据发送(虽然解决了服务器的并发访问问题,但是对于大量的数据传输却手足无措)
			小意外:当服务器端退出,此时客户端不再阻塞,正常执行函数体。(这就说明了,此时recv函数为非阻塞状态=》那么服务器和客户端同时运行,为什么会发生阻塞?)

补充:
(1)如果将服务器端accept函数放在while循环外部(对比TCP文件传输):
	1)只有一个客户端能够与服务器建立连接并进行数据收发;其它客户端被阻塞,无法与服务器建立连接。(问题:(1)服务器只能与一个客户端建立连接?(2)那么如何解决这个问题?(3)是从服务端解决这个问题,还是从客户端解决这个问题?	先解决问题(3):显然,要解决这个问题肯定是要从服务器端去解决--客户端是向服务器端发起连接请求,那么具体是否能够建立连接,显然是取决于服务器端的意愿和能力;所以,多个客户端向服务器端发起连接请求,能不能实现的关键在于服务器能不能接受多个客户端接入,服务器端是否允许多个客户端接入。	下面再解决问题(2):解决这个问题,其实用一句话来表述就是解决服务器并发访问问题,这个问题后面专项解决,现在只需要明白所面临的问题是服务器并发访问的问题即可。)

(2)如果将connect函数放在循环外部,将accept函数放在循环外部,此时意味着:客户端与服务器端第一次建立连接,可以发送一次数据;发完数据接着进行第二次,第三次。。。连接请求;此时当然是报错!因为同一个网络套接字只能建立一次连接,不能重复建立连接(这是由TCP通信机制决定的);但是这种方式可以将服务器同时与多个客户端建立连接。。。。。。。。。。。。。。总结一下就是:客户端与服务器端要进行多次请求连接-建立连接;那么每进行一次通信,都必须关闭(close)通信套接字(已经建立三次握手,四次挥手连接的套接字confd-accept)。

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到