TCP服务器/客户机开发“框架”

服务器端:

/*Socket 服务器框架*/
#include<stdio.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<unistd.h>
#define nLISTEN  5

/*出错处理函数*/
void error(int status , int err, char *str){
	fprintf(stderr,"%s,return val is : %d, error:%s\n",str,status,strerror(err));
	exit(1) ;
}

/*设置struct sockaddr_in结构体local*/
void set_address(char *hname, char *sname, struct sockaddr_in *sap, char *protocol){
	struct hostent *hp ;	
	struct servent *sp ;
	short port ;
	char *endptr ;
	memset(sap,0,sizeof(sap));
	sap->sin_family = AF_INET ; /*协议族*/	
	if(hname != NULL){
		/* 命令行中提供了主机的地址 */		
		if( !inet_aton( hname , &sap->sin_addr ) ){
			/* 先把主机地址当作点分十进制处理,用inet_aton将主机字节的IP地址转换为网络字节的地址 */			
			hp = gethostbyname( hname ) ;
			if( hp == NULL )
				error( 1, errno ,"gethostbyname failed!");
			/* 此时的hp->h_addr是网络字节形式的,不能直接用printf打印出来 */
			sap->sin_addr = *(struct in_addr *)(hp->h_addr) ;		
		}
	}
	else
		sap->sin_addr.s_addr = htonl( INADDR_ANY ) ;		/*监听任意IP,制定端口*/
	/*将字符形式的端口号转化为十进制形式 */
	port = strtol(sname , &endptr , 0 ) ;
	if( *endptr == 0 ){
		sap->sin_port = htons(port) ;
	}
	else{
		/* 端口不是字符形式的整数 */
		sp = getservbyname( sname, protocol );
		if( sp == NULL )
			error( 1, errno ,"getservbyname failed!");	
		else{
			sap->sin_port = sp->s_port ;
		}
	}
}
/* 服务器应用函数 */
void server(int s1 , struct sockaddr_in *peerp){
	char buf[20] ;
	int bytes ;
	bytes = recv(s1,buf ,20 , 0);
	if(bytes < 0)
		error( 1 , errno , "Server recv failed!");
	buf[bytes] = 0 ;
	printf("Server received : %s\n",buf);
	strcpy(buf, "I am Server!");
	if( send( s1, buf,20,0) < 0)
		error( 1, errno , "send failed!");
	sleep(4);
	printf("Server is quiting...\n");
}

int main(int argc, char *argv[]){
	int s ,peerlen ,s1;	
	char *host_name,*port_name ;
	const int on = 1 ;
	int i ;
	struct sockaddr_in local ,peer;
	if(argc == 3){
		host_name = argv[1] ;		/* 监听制定IP地址 */
		port_name = argv[2] ;		/* 监听制定的端口号 */
	}
	else if(argc == 2){
		host_name = NULL ;		/* IP设置为默认 */
		port_name = argv[1] ;	
	}
	else if(argc == 1 || argc > 3){
		fprintf(stderr,"Usage:filename <hostname> <portname>\n");
		exit(1);
	}
	s = socket(AF_INET,SOCK_STREAM,0);
	if(s < 0)
		error( 1, errno ,"socket failed!");
	set_address(host_name , port_name ,&local , "tcp") ;
	if( setsockopt( s, SOL_SOCKET, SO_REUSEADDR, &on ,sizeof(on) ) )
		error( 1, errno , "setsockopt failed!");
	if( bind( s,(struct sockaddr *)&local ,sizeof(local) ) )
		error( 1 , errno , "bind failed!");
	if( listen( s, nLISTEN) )
		error( 1 , errno , "listen failed!");
	
	do{	
		peerlen = sizeof( peer ) ;		
		s1 = accept( s, (struct sockaddr *)&peer,&peerlen);			
		if(s1 < 0)
			error( 1, errno , "accept failed!");
		server( s1 , &peer);
		close(s1) ;
	}while(1) ;
	return 0 ;
}

客户机端:

/*Socket 客户机框架*/
#include<unistd.h>
#include<stdio.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<netdb.h>
#include<errno.h>
#include<stdlib.h>
#include<string.h>

void error(int status , int err, char *str){
	fprintf(stderr,"%s, return status is : %d , error:%s\n",str,status,strerror(errno));
	exit(1) ;
}

void set_address(char *hname, char *sname ,struct sockaddr_in *sap, char *protocol){
	struct hostent *hp ;	
	struct servent *sp ;
	short port ;
	char *endptr ;
	memset(sap,0,sizeof(sap));
	//memset(vis,0,sizeof(vis));
	sap->sin_family = AF_INET ;
	if( hname != NULL ){
		if( !inet_aton(hname, &sap->sin_addr) ){
			hp = gethostbyname( hname );
			if( hp == NULL )
				error( 1, errno ,"gethostbyname failed!");
			sap->sin_addr = *(struct in_addr *)(hp->h_addr) ;
		}
	}
	else{
		sap->sin_addr.s_addr = htonl( INADDR_ANY );	
	}
	
	port = strtol( sname , &endptr , 0) ;
	if( *endptr == 0 ){
		sap->sin_port = htons(port);		
	}
	else{
		sp = getservbyname( sname ,protocol);
		if( sp == NULL )
			error( 1 , errno , "getservbyname failed!");
		sap->sin_port = sp->s_port ;
	}
}

void client(int s , struct sockaddr_in *peer){
	char buf[20] = "I am Client." ;
	int bytes; 
	send(s , buf, 20 , 0 );
	
	bytes = recv(s ,buf, 20 , 0 ) ;
	if(bytes < 0)
		error(1,errno ,"recv failed!");
	buf[bytes] = 0 ;
	printf("Client received : %s\n",buf);
	printf("Client sleep...\n");	
	sleep(5);
	printf("Client wake up!\n");
	printf("Client quiting...\n");
}
int main(int argc, char *argv[]){
	int s , peerlen ;
	char *host_name ,*port_name ; 
	struct sockaddr_in peer ;	
	if( argc == 3 ){
		host_name = argv[1] ;
		port_name = argv[2] ;
	} 
	else if(argc == 2){
		host_name = NULL ;
		port_name = argv[1] ;
	}
	else if(argc < 2 || argc > 4){
		printf("Usage : filename <hostname> portname\n");
		exit(1) ;		
	}
	s = socket( AF_INET,SOCK_STREAM,0);
	if(s < 0)
		error(1 , errno , "socket failed!");
	set_address(host_name, port_name, &peer, "tcp") ;
	if( connect(s, (struct sockaddr *)&peer, sizeof(peer)) )
		error( 1 , errno , "connet failed!");
	client(s, &peer);
	return 0 ;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值