www.pudn.com > unixtonxunchengxu.rar > UnionTCPIPSvr.c


/*
	socket通讯中,若客户端和服务器建立长链接,服务器程序关闭链接,终止进程后,
	若客户端没有关闭该链接,则不能重新启动服务器程序,bind函数调用失败。
	在服务器程序的accept函数调用之后增加语句,即使客户端没有关闭链接,
	服务器程序也可以主动关闭socket链接,重新启动。
*/

#include 
#include 

#include 
#include 
#include 
#include 

#ifndef _UnionSocket_2_x_
#define _UnionSocket_2_x_
#endif

#define _UnionTask_2_x_
#include "UnionSocket.h"

int UnionTCPIPServer(int port,char *ServerName,int (*UnionTCPIPTaskServer)())
{
	struct sockaddr_in	serv_addr;
	int			scksvr;
	struct sockaddr_in	cli_addr;
	int			sckinstance;
	int			clilen;
	char			cliip[40];
	int			ret;
	struct linger		Linger;	// Added by Wolfgang Wang, 2003/02/26
	
	// Initialize the socket
	memset((char *)(&serv_addr), 0,sizeof(struct sockaddr_in));
	serv_addr.sin_family            = AF_INET;
	serv_addr.sin_addr.s_addr       = htonl(INADDR_ANY);
	serv_addr.sin_port = htons((u_short)port);

	if ((scksvr = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		UnionSystemErrLog("in UnionTCPIPServer:: socket()!\n");
		return(UnionErrCallingSocket);
	}

	if (bind(scksvr,(struct sockaddr *)(&serv_addr),sizeof(struct sockaddr_in)) < 0)
	{
		UnionSystemErrLog("in UnionTCPIPServer:: bind()!\n");
		return(UnionErrCallingBind);
	}

	// Listen to new-coming connecting request
	if ( listen(scksvr, 10000) < 0 )
	{
		UnionSystemErrLog("in UnionTCPIPServer:: listen()!\n");
		return(UnionErrCallingListen);
	}

	if (UnionCreateProcess() > 0)
		return(0);

	UnionRegisterTask("%s %d",ServerName,port);
	UnionSuccessLog("in UnionTCPIPServer:: %s %d is started OK!\n",ServerName,port);
			
	for (;;)
	{
		// Accept a Client's Connecting reqeust.
		clilen = sizeof(cli_addr);
		sckinstance = accept(scksvr, (struct sockaddr *)&cli_addr,&clilen);
		if ( sckinstance < 0 )
		{
			UnionSystemErrLog("in UnionTCPIPServer:: accept()!\n");
			continue;
		}
		
		// Added by Wolfgang Wang, 2003/02/26
		Linger.l_onoff = 1;
		Linger.l_linger = 0;
		if (setsockopt(sckinstance,SOL_SOCKET,SO_LINGER,(char *)&Linger,sizeof(Linger)) != 0)
		{
			UnionSystemErrLog("in UnionCreatSocketClient:: setsockopt linger!");
			close(sckinstance);
			return(UnionErrCallingSetsockopt);
		}
		// End of Addition of 2003/02/26
		
		// Create a new process or a new thread, one of the two process is listening
		// to other connecting request from clients, whereas the other is to fulfill
		// the task and return a response to the connected client, when necessary.
		// When the task process finish fulfiling the task, it should terminate itself
		// automatically.
	    	switch (UnionCreateProcess())
		{
			case 0:
				UnionRegisterTask("%s %d",ServerName,port);
				UnionCloseSocket(sckinstance);
				continue;
			case -1:
				UnionUserErrLog("in UnionTCPIPServer:: UnionCreateProcess!\n");
				UnionCloseSocket(sckinstance);
				continue;
			default:
				UnionUnregisterTask();
				if ( (ret = (*UnionTCPIPTaskServer)(sckinstance,inet_ntoa(cli_addr.sin_addr),port)) != 0)
					UnionUserErrLog("in UnionTCPIPServer:: UnionTCPIPTaskServer!\n");
				UnionCloseSocket(sckinstance);
				return(ret);
		}
				
    	}
}