Linux多线程一

本文介绍了一个客户端与服务器端通信实现的代理程序,包括客户端发送与接收消息的功能,以及服务器端处理请求和响应的过程。通过使用多线程进行并发处理,实现了高效的数据传输。程序使用了socket编程技术,展示了网络通信的基本原理和实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

客户端

#include<stdio.h>
#include<stdlib.h>  
#include<string.h>  
#include<sys/types.h>  
#include<sys/socket.h>  
#include<netinet/in.h>  
#include<netinet/ip.h>  
#include<unistd.h>  
#include<errno.h>  
#include<pthread.h>  
#define MAXN 1024

static void *thread_send(void *arg)  
{  
	    char str[MAXN];  
	    int st = *(int *) arg;
	    // pthread_detach(pthread_self());	
	    while (1)  
	    {  
			 memset(str, 0, sizeof(str));  
		     read(STDIN_FILENO, str, sizeof(str));  
			 if (send(st, str, strlen(str), 0) == -1)  
			 {  
				 printf("send error:%s \n", strerror(errno));  
				 break;  
			 }  
	    }
	    // pthread_detach(pthread_self());	
	    return NULL;  
}

static void* thread_recv(void *arg)  
{  
	    char str[MAXN];  
	    int st = *(int *) arg;
	    // pthread_detach(pthread_self());	
	    while (1)  
	    {  
              memset(str, 0, sizeof(str));  
			  int rv = recv(st, str, sizeof(str), 0);  
			  if (rv <= 0)  
			  {  
				 if(rv == 0)
				 {  
                   printf("server have already full !\n");  
				   exit(0);  
			     }  
			     printf("recv error:%s \n", strerror(errno));  
				 break;  
			   }  
		       printf("%s",str);  
		 }
		 // pthread_detach(pthread_self());
		 return NULL;  
}  

int run_client(char *ip,int port)
{
	int clientfd;
	pthread_t tid1,tid2;
	struct sockaddr_in client_addr;

    if((clientfd = socket(AF_INET,SOCK_STREAM,0))<0)
	  return -1;
    
    memset(&client_addr,0,sizeof(client_addr));
	
	client_addr.sin_family = AF_INET;
	client_addr.sin_addr.s_addr = inet_addr(ip);
    client_addr.sin_port = htons(port);

	if(connect(clientfd, (struct sockaddr*)&client_addr,sizeof(client_addr))<0)
	  return -1;

	if(pthread_create(&tid1,NULL,thread_send,&clientfd)!=0)
	  return -1;

	if(pthread_create(&tid2,NULL,thread_recv,&clientfd)!=0)
	  return -1;
	pthread_join(tid1, NULL);  
    pthread_join(tid2, NULL);
    close(clientfd);
	return 0;
}

int main(int argc, char *argv[])
{
    if(argc < 3)
	{
       printf("ip port,example:127.0.0.1 8080\n");
	   return -1;
	}
	char *ip = argv[1];
	int port = atoi(argv[2]);
    run_client(ip,port);
	return 0;
}



服务器端

#include<stdio.h>  
#include<stdlib.h>  
#include<string.h>  
#include<sys/types.h>  
#include<sys/socket.h>  
#include<netinet/in.h>  
#include<netinet/ip.h>  
#include<arpa/inet.h>  
#include<unistd.h>  
#include<errno.h>  
#include<pthread.h>

#define MAXN 1024
#define backlog 5

int count_client=0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

struct pthread_socket  
{  
	 int st;  
	 pthread_t tid;  
};

static void *thread_send(void *arg)  
{  
	    char str[MAXN];  
		int st = *(int *) arg;	
		memset(str, 0, sizeof(str));  
		strcpy(str, "hello,welcome to you! \n");  
		if (send(st,str, strlen(str), 0) == -1)  
		{  
			printf("send error:%s \n", strerror(errno));  
			return NULL;  
		}  
		while (1)  
		{  
			memset(str, 0, sizeof(str));  
			read(STDIN_FILENO, str, sizeof(str));  
		    if(send(st, str, strlen(str), 0) == -1)  
			{  
				printf("send error:%s \n", strerror(errno));  
				break;  
			}  
        }
		pthread_detach(pthread_self());
	    return NULL;  
}

static void* thread_recv(void *arg)  
{  
	    char str[MAXN];  
		struct pthread_socket *tmp = (struct pthread_socket *) arg;  
		int st = tmp->st;  
		pthread_t tid = tmp->tid;  
		while (1)  
		{  
			memset(str, 0, sizeof(str));  
	        int rv = recv(st, str, sizeof(str), 0);  
			if (rv < 0)  
			{  
				printf("recv error:%s \n", strerror(errno));  
				break;  
			}  
		    if (rv == 0)  
			{  
				break;  
			}  
			printf("%s", str);  
		}  
		pthread_cancel(tid);  
		pthread_mutex_lock(&mutex);  
	    count_client--;  
		pthread_mutex_unlock(&mutex);  
		close(st);
        pthread_detach(pthread_self());
		return NULL;  
}  

int create_listen(int port)
{
	int listen_st;
	struct sockaddr_in sockaddr;
	if((listen_st = socket(AF_INET,SOCK_STREAM,0))<0)
	  return -1;
	sockaddr.sin_family = AF_INET;
	sockaddr.sin_port = htons(port);
	sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	if (bind(listen_st, (struct sockaddr *) &sockaddr, sizeof(sockaddr))<0)
	  return -1;
    if (listen(listen_st,backlog)<0)
	  return -1;
	return listen_st;
}

int accept_socket(int listen_st)
{
	int accept_st,clientlen;
	struct sockaddr_in accept_sockaddr;
	clientlen=sizeof(accept_sockaddr);
	memset(&accept_sockaddr, 0,clientlen);
    accept_st = accept(listen_st, (struct sockaddr*) &accept_sockaddr, &clientlen);
    if(accept_st<0)
      return -1;
    printf("accpet ip:%s \n", inet_ntoa(accept_sockaddr.sin_addr));
    return accept_st;	
}

int run_server(int port)
{
    int listen_st = create_listen(port);
	pthread_t tid1,tid2;
	int accept_st;
	struct pthread_socket tmp;
	if(listen_st<0) return -1;
	printf("server start\n");
	while(1)
	{ 
        if((accept_st = accept_socket(listen_st))<0)
	      return -1;
        
        if(count_client>=2)
        {
			printf("connect have already be full! \n");  
		    close(accept_st);  
		    continue;
		}
        pthread_mutex_lock(&mutex);  
        count_client++;
        pthread_mutex_unlock(&mutex);
        if(pthread_create(&tid1, NULL, thread_send, &accept_st)!= 0)
        {
			printf("create thread error:%s \n", strerror(errno));  
			break;
		}

        tmp.st=accept_st;
		tmp.tid=tid1;

		if (pthread_create(&tid2, NULL, thread_recv, &tmp)!= 0)
		{
			printf("create thread error:%s \n", strerror(errno));  
			break;
		}

        		
	}
	close(accept_st);  
    close(listen_st);  
	return 0;  

}

int main(int argc, char *argv[])
{
	 if (argc < 2)  
	 {  
		 printf("port,example:8080 \n");  
		 return -1;  
	 }
     int port = atoi(argv[1]);  
    if (!port)   printf("port error! \n");  
    else         run_server(port);
    return 0;	
}

Makefile

LIBS = -lpthread
OBJS1 = client.o
OBJS2 = server.o
main: ${OBJS1} ${OBJS2}
	cc -o client ${OBJS1} ${LIBS}
	cc -o server ${OBJS2} ${LIBS}
clean:
	rm -f main ${OBJS1} ${OBJS2}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值