30网络通信之多线程

Posted gd-luojialin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了30网络通信之多线程相关的知识,希望对你有一定的参考价值。

使用原始的Socket模式,会发生阻塞问题,只能收一条消息再发一条消息。无法做到发送多次消息。

 

在服务器端创建多线程,每当accept()接受到一个客户端时,启动一条线程单独去处理。

 

 技术图片

 

代码:

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

#define SRV_PORT  0xabcd
#define CLT_PORT  0xaaaa

void *Comm_thread(void *param)
{
	int fd = *(int*)param;
	int iRet;
	char szBuf[1024];
	char szMsg[] = "I Received!";

	while(1)
	{
		memset(szBuf, 0, 1024);
		iRet = read(fd, szBuf, 1024);
		if (iRet < 0)
		{
			perror("Recv failed!");
			break;
		}
		if (iRet == 0)
		{
			printf("Disconnect!
");
			break;
		}
		else
		{
			printf("Recv:%s
", szBuf);
			
			//write(fd, szMsg, sizeof(szMsg));
		}
	}
	close(fd);

	return NULL;
}


void Tcp_server()
{
	int fd;
	int iRet;
	struct sockaddr_in  addr;
	socklen_t addrlen = sizeof(addr);

	fd = socket(PF_INET, SOCK_STREAM, 0);//IPPROTO_IP
	if (fd < 0)
	{
		perror("Socket failed!");
		return;
	}
	
	addr.sin_family = AF_INET;//use IPV4 address
	addr.sin_port   = htons(SRV_PORT);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);//INADDR_ANY=0L;
	
	iRet = bind(fd, (struct sockaddr*)&addr, addrlen);
	if (iRet)
	{
		perror("Bind failed!");
		close(fd);
		return;
	}

	iRet = listen(fd, 10);
	if (iRet)
	{
		perror("Listen failed!");
		close(fd);
		return;
	}

	int clientfd;
	struct sockaddr_in srcaddr;
	char szTip[] = "Welcome!";
	//char szBuf[1024]={};

	while(1)
	{
		clientfd = accept(fd,  (struct sockaddr*)&srcaddr, &addrlen);
		if (clientfd < 0)
		{
			perror("Accept failed!");
			break;
		}

		printf("Connect form %s[%d]
", inet_ntoa(srcaddr.sin_addr), ntohs(srcaddr.sin_port));

		//send(clientfd, szTip, strlen(szTip), 0);
		write(clientfd, szTip, strlen(szTip)); //send data to client

		pthread_t  tid;
		pthread_create(&tid, NULL, Comm_thread, (void*)&clientfd);
	}

	close(fd);

	return ;

}


void Tcp_client()
{
	char szDestIp[16];
	int  port;

	fprintf(stderr, "Connect to:");
	scanf("%s%d", szDestIp, &port);

	int fd;
	int iRet;
	struct sockaddr_in srvaddr;
	socklen_t addrlen = sizeof(srvaddr);

	fd = socket(PF_INET, SOCK_STREAM, 0);
	if (fd < 0)
	{
		perror("Socket failed!");
		return;
	}

	srvaddr.sin_family = AF_INET;
	srvaddr.sin_port  = htons((short)port);
	srvaddr.sin_addr.s_addr = inet_addr(szDestIp);

	iRet = connect(fd, (struct sockaddr*)&srvaddr, addrlen);
	if (iRet)
	{
		perror("Connect failed!");
		return;
	}

	char szBuf[1024];
	char szMsg[100];
	while(1)
	{
		memset(szBuf, 0, 1024);
		iRet = read(fd, szBuf, 1024);//receive message
		if (iRet < 0)
		{
			perror("Read failed!");
			break;
		}
		if (iRet == 0)
		{
			printf("Server disconnected
");
		}

		printf("Recv: %s
", szBuf); 

		fprintf(stderr, "Send:");
		memset(szMsg, 0, 100);
		read(STDIN_FILENO, szMsg, 100);//get message
		
		write(fd, szMsg, strlen(szMsg)); //send message

	}

}



int main(int argc, char** argv)
{
	if (argc!=2 
	   || (strcmp(argv[1], "s") && strcmp(argv[1], "c")  )
           )
	{
		printf("Usage: %s [ c | s ]
", argv[0]);
		printf("	 c : For start tcp client
");
		printf("	 s : For start tcp server
");	
		return 0;
	}
	
	if (argv[1][0] == ‘s‘)
	{
		Tcp_server();
	}
	else if (argv[1][0] == ‘c‘)
	{
		Tcp_client();
	}

	return 0;
}

  

以上是关于30网络通信之多线程的主要内容,如果未能解决你的问题,请参考以下文章

网络编程之多线程

iOS多线程与网络开发之多线程概述

面试宝典2之多线程网络篇

iOS多线程与网络开发之多线程NSThread

delphi之多线程编程

boost库之多线程间通信