TCP利用多进程和多线程实现服务器端的并发处理

  • 实验目的

熟练掌握服务器端并发处理的方法。

  • 实验要求

在TCP文件传输代码的基础上,利用多进程和多线程实现服务器端的并发处理。

  • 实验步骤

 

1.利用多进程实现服务器端的并发处理

 

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <netinet/in.h>
#include <errno.h>
#include <memory.h>
#include <stdlib.h>  //for malloc
#include<arpa/inet.h>
#include<sys/wait.h>
#include<signal.h>
#define MAXLINE 4096
#define BUFFER_SIZE 1024
void recvfilename(int temp)
{
    char filename[100];
    char filepath[100];
    memset(filename,'\0',sizeof(filename));
    memset(filepath,'\0',sizeof(filepath));
    char *buffer;//file buffer
    buffer = (char *)malloc(sizeof(char)*BUFFER_SIZE);
    bzero(buffer,BUFFER_SIZE);
    int lenfilepath;
    int fileTrans;
    lenfilepath = recv(temp,filepath,100,0);
    printf("filepath :%s\n",filepath);
    
    FILE *fp;
    int writelength;
    if(lenfilepath<0)
    {
        printf("recv error!\n");
    }
    //从路径中提取出文件名
    else
    {
        int i=0,k=0;
        for(i=strlen(filepath); i>=0; i--)
        {
            if(filepath[i]!='/')
            {
                k++;
            }
            else
                break;
        }
        strcpy(filename,filepath+(strlen(filepath)-k)+1);
    }
    printf("filename :%s\n",filename);
    //以写的方式打开文件
    fp = fopen(filename,"w");
    if(fp!=NULL)
    {
        //接受文件内容buffer,存在buffer中
        while(fileTrans =recv(temp,buffer,BUFFER_SIZE,0))
        {
            if(fileTrans<0)
            {
                printf("recv error!\n");
                break;
            }
            //把buffter中的文件内容写到fp指针指的文件中
            writelength = fwrite(buffer,sizeof(char),fileTrans,fp);
            if(writelength <fileTrans)
            {
                printf("write error!\n");
                break;
            }
            bzero(buffer,BUFFER_SIZE);
            //memset(buffer,0,sizeof(buffer));
        }
        printf("recv finished!\n");
        fclose(fp);
    }
    exit(0);
}

int main()
{
    int temp;//accept
    struct sockaddr_in client;
    socklen_t addrlen;
    int sockfd;
    
    //创建套接字
    sockfd = passiveTCP("6666", 10);
    //(void) signal(SIGCHLD,reaper);
    addrlen = sizeof(client);
    while(1)
    {
        temp = accept(sockfd,(struct sockaddr*)&client,&addrlen);
        if(temp <= 0)
        {
            printf("accept error!\n");
            close(temp);
        }
        else
        {
            printf("client IP:   %s\n",inet_ntoa(client.sin_addr));
        }
	switch(fork())
	{
	    case 0:     /*child*/
		(void) close(sockfd);
		recvfilename(temp);
	    default:    /*parent*/
		(void) close(temp);
		break;
	    case -1:
		printf("fork error");
	}
        //接受文件路径,返回文件路径的长度
       // recvfilename(temp);

    }
    return 0;
}

在windows下写了个aa.txt文本内容是hello

 运行windows下客户端代码 输入相对路径下的aa.txt文本文件 发现发送成功

 

 

在linux下服务器 

 2.一个进程多个线程实现

 

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <netinet/in.h>
#include <errno.h>
#include <memory.h>
#include <stdlib.h>  //for malloc
#include<arpa/inet.h>
#include<pthread.h>
#define MAXLINE 4096
#define BUFFER_SIZE 1024
void recvfilename(int temp)
{
    char filename[100];
    char filepath[100];
    memset(filename,'\0',sizeof(filename));
    memset(filepath,'\0',sizeof(filepath));
    char *buffer;//file buffer
    buffer = (char *)malloc(sizeof(char)*BUFFER_SIZE);
    bzero(buffer,BUFFER_SIZE);
    int lenfilepath;
    int fileTrans;
    lenfilepath = recv(temp,filepath,100,0);
    printf("filepath :%s\n",filepath);
    
    FILE *fp;
    int writelength;
    if(lenfilepath<0)
    {
        printf("recv error!\n");
    }
    //从路径中提取出文件名
    else
    {
        int i=0,k=0;
        for(i=strlen(filepath); i>=0; i--)
        {
            if(filepath[i]!='/')
            {
                k++;
            }
            else
                break;
        }
        strcpy(filename,filepath+(strlen(filepath)-k)+1);
    }
    printf("filename :%s\n",filename);
    //以写的方式打开文件
    fp = fopen(filename,"w");
    if(fp!=NULL)
    {
        //接受文件内容buffer,存在buffer中
        while(fileTrans =recv(temp,buffer,BUFFER_SIZE,0))
        {
            if(fileTrans<0)
            {
                printf("recv error!\n");
                break;
            }
            //把buffter中的文件内容写到fp指针指的文件中
            writelength = fwrite(buffer,sizeof(char),fileTrans,fp);
            if(writelength <fileTrans)
            {
                printf("write error!\n");
                break;
            }
            bzero(buffer,BUFFER_SIZE);
            //memset(buffer,0,sizeof(buffer));
        }
        printf("recv finished!\n");
        fclose(fp);
    }
}

int main()
{
    int temp;//accept
    struct sockaddr_in client;
    socklen_t addrlen;
    int sockfd;
    
    //线程
    pthread_t th;
    pthread_attr_t ta;
    pthread_attr_init(&ta);
    pthread_attr_setdetachstate(&ta, PTHREAD_CREATE_DETACHED);
    //创建套接字
    sockfd = passiveTCP("6666", 10);
   

    //if(pthread_create(&th, &ta, (void* (*)(void*))prstats, 0) < 0)
	//errexit("pthread_create(prstats): %s\n", strerror(errno));

    addrlen = sizeof(client);
    while(1)
    {
        temp = accept(sockfd,(struct sockaddr*)&client,&addrlen);
        if(temp <= 0)
        {
            printf("accept error!\n");
            close(temp);
        }
        else
        {
            printf("client IP:   %s\n",inet_ntoa(client.sin_addr));
        }
    	pthread_create(&th, &ta, (void *(*)(void *))recvfilename, (void *)temp);
	//errexit("pthread_create: %s\n", strerror(errno));
        //接受文件路径,返回文件路径的长度
       // recvfilename(temp);

    }
    return 0;
}

 

多进程实现服务器简单的调用了fork函数,在每次连接到达时创建一个新的进程去处理,主进程不处理传输过程,只是接受连接。如果并发服务器用一个进程多个线程来实现的话,优点相较单线程多进程来说上下文开销更小,但缺点是一个线程的动作可能会对其他线程产生影响

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值