使用多线程在CentOS里编写类似QQ的聊天程序

@使用多线程在CentOS里编写类似QQ的聊天程序

说明一下编写的思路和流程

首先我们要知道TCP/IP协议在liunx下的操作流程(这部分书上或者网上一堆)。其次,还要知道有socket里有多少函数能阻塞线程。这部分很重要,笔者在写的时候就被这些忽悠了遍。
本次程序使用到带有阻塞的函数
1、连接时阻塞线程的函数:accpet();
原型:SOCKET accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
2、读取时阻塞函数:recv()
原型: int recv(int new_fd, void *buf, int len, unsigned int flags);
第一参数:accpet返回的值
第二参数:缓冲区
第三参数:缓冲区长度
第四参数:一般为0
本次试验主要的线程函数
其实也没有什么特殊的就是pthread_create()
原型:int pthread_create((pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
第一参数:pthread_t 类型的变量
第二参数:一般UNLL表示手动结束
第三参数:方法指针
第四参数:传递给方法的参数
第四参数很重要,我没有仔细看文档踩了很多雷。
*编写思路
不多说上图
服务器端在这里插入图片描述主要思路是利用accpet()和recv()函数本身自带的阻塞去控制线程的创建和消息的发送。
客户端
在这里插入图片描述
主要的想法是,分别利用两个阻塞控制用户端的显示。同时,使用延时,保证两个线程正常显示,给用户好的使用体验。
代码
service.c

#include<stdio.h>

#include<stdlib.h>

#include<errno.h>

#include<string.h>

#include<sys/types.h>

#include<netinet/in.h>

#include<sys/socket.h>

#include<sys/wait.h>

#include<unistd.h>

#include<arpa/inet.h>

#include<pthread.h>

#define MAXBUF 1024

void* conClient(void* fd);

void *recvClient(void *fd);

static char buf[MAXBUF+1];

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

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

	socklen_t len;
	
	int pid;

	int sockfd,new_fd;

	struct sockaddr_in my_addr,their_addr;

	unsigned int myport,lisnum;

	//char buf[MAXBUF+1];

	if(argv[2])

		myport=atoi(argv[2]);

	else

		myport=8088;

	if(argv[3])

		lisnum=atoi(argv[3]);

	else

		lisnum=5;

	if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)

	{

		perror("socket");

		exit(EXIT_FAILURE);

	}

 

	bzero(&my_addr,sizeof(my_addr));

	my_addr.sin_family=AF_INET;

	my_addr.sin_port=htons(myport);

	if(argv[1])

		my_addr.sin_addr.s_addr=inet_addr(argv[1]);

	else

		my_addr.sin_addr.s_addr=INADDR_ANY;

	if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))==-1)

	{

		perror("bind");

		exit(EXIT_FAILURE);

	}

	if(listen(sockfd,lisnum)==-1)

	{
		perror("listen");

		exit(EXIT_FAILURE);

	}

	while(1)

	{
		//sleep(500);
			
		pthread_t con;		

		printf("wait for connect!\n");		
	
		len=sizeof(struct sockaddr);

		new_fd=accept(sockfd,(struct sockaddr *)&their_addr,&len);
		
		printf("accept true new_fd:%d\n\n",new_fd);
	
		int k;		

		printf("server:got connection from %s,port %d,socket %d\n",inet_ntoa(their_addr.sin_addr),ntohs(their_addr.sin_port),new_fd);
				
		k = pthread_create(&con, NULL, conClient, (void*)new_fd);

		printf("%d\n",k);

		printf("newfd=%d\n",new_fd);
	}
	close(sockfd);
}
void *conClient(void* fd){

	int new_fd = (int)fd;

	char* buf1 = "wlecome Like QQ";
	
//	char buf[1024];
	
	strcpy(buf,buf1);	

	pthread_detach(pthread_self());

	int len;

	pthread_t con; 

	pthread_create(&con,NULL,recvClient,(void*)new_fd);
	
	while(1)
	{
		printf("wait\n");
			
		len=recv(new_fd,buf,strlen(buf),0);
			
		printf("message:%s\t recv sucessful,send %dbyte!\n",buf,len);
		if(len < 0)
		{
			break;
		}			

	}
	close(new_fd);
	pthread_exit(NULL);
}

void *recvClient(void * fd)
{
	int len;	

	int new_fd = (int)fd;

	while(1)
	{
		//printf("len : %d",strlen(buf));
		if(strlen(buf) > 0)
		{
			len=send(new_fd,buf,sizeof(buf),0);	
			printf("send message: %S len : %d",buf,len);
			sleep(1);
			bzero(buf,strlen(buf));
		}
	}

	close(new_fd);
	pthread_exit(NULL);
}

client.c

#include<stdio.h>

#include<string.h>

#include<errno.h>

#include<sys/socket.h>

#include<resolv.h>

#include<stdlib.h>

#include<netinet/in.h>

#include<arpa/inet.h>

#include<unistd.h>

#define MAXBUF 1024

void* recv_client(void * fd);

int main(int argc,char **argv)

{

	int sockfd,len;

	struct sockaddr_in dest;

	char buffer[MAXBUF+1];
	char sendbuf[MAXBUF+1];

	if(argc!=3)

	{

		printf("error format,it must be:\n\t\t%s IP port\n",argv[0]);

		exit(EXIT_FAILURE);

	}

	if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)

	{

		perror("Socket");

		exit(errno);

	}

	printf("socket created\n");

	bzero(&dest,sizeof(dest));

	dest.sin_family=AF_INET;

	dest.sin_port=htons(atoi(argv[2]));

	if(inet_aton(argv[1],(struct in_addr *)&dest.sin_addr.s_addr)==0)

	{

		perror(argv[1]);

		exit(errno);

	}

	if(connect(sockfd,(struct sockaddr *)&dest,sizeof(dest))==-1)

	{

		perror("Connect");

		exit(errno);

	}

	printf("server connected\n");

	pthread_t tid;

	int ret;

 	ret = pthread_create(&tid,NULL,recv_client,(void *)sockfd);

	if(0 > ret)
	{

 		perror("pthread_create");


	 	return -1;
	
 	}

	sleep(1);	

	while(1)

	{	
	
		bzero(sendbuf,MAXBUF+1);

		printf("pls send message to send:");

		fgets(sendbuf,MAXBUF,stdin);

		if(!strncasecmp(sendbuf,"quit",4))

		{

			printf("i will quit!\n");

			break;

		
		}
	
		len=send(sockfd,sendbuf,strlen(sendbuf)-1,0);

		if(len<0)

		{

			printf("message '%s' send failure,errno code is %d,errno message is '%s'\n",buffer,errno,strerror(errno));

			break;

		}

		else
		{
			sleep(1);
		}

	}

	close(sockfd);

	return 0;

}
void * recv_client(void* fd)
{
	
	char recvbuf[1024];

	int sockfd = (int)fd;	 

	while(1)
      	{
	
           int ret = recv(sockfd,recvbuf,sizeof(recvbuf),0);

           if(0 > ret)

           {

              perror("recv");

              return;

           }

            printf("\nmessage from server: %s\n",recvbuf);
		
//	    printf("\npls send message to send:");	
	
	    bzero(recvbuf,1025);
        }
}


代码效果图
在这里插入图片描述
结语
本次第一次在liunx上做一些程序,这是我们的作业。有不好的地方希望指正。
参考链接
https://www.cnblogs.com/gildoringlorin/p/3949765.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值