socket远程执行linux服务器程序

本文介绍了一个简单的TCP客户端和服务器程序的实现方法,包括如何建立连接、数据收发及命令处理等核心功能。适用于初学者理解TCP通信的基本原理。

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

/***************************************************
* client.c
* 在Red Hat 9.0 GCC下调试通过!
* 在运行服务器端程序之后,
* 再运行客户端,否则,连接会失败!
* ./client 你的ip地址 [端口]
* 呵呵!!
* GoodLuck
***************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<netdb.h>
#include<sys/socket.h>
#include<sys/time.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<arpa/inet.h>

#define BUFSIZE 8192
#define DEFAULT_PORT 5320

enum {SMD_NAME,DST_IP,DST_PORT};

int main(int argc,char *argv[])
{
	struct sockaddr_in server;    //服务器地址
	unsigned long dst_ip;         //服务器IP地址
	int port;     //端口号
	int s;        //套接字的描述符
	int n;        //输入数据的字节数
	char buf[BUFSIZE];    //接收缓
	char cmd[BUFSIZE];    //发送缓
	struct timeval tv;    //select超时时间
	fd_set readfd;        //使用select检索出的描述符

	//实际参数的检查
	if(argc!=2 && argc!=3){
		fprintf(stderr,"Usage: %s hostname[port]\n",argv[0]);
		exit(EXIT_FAILURE);
	}

	//检索服务器的ip地址
	if((dst_ip=inet_addr(argv[DST_IP]))==INADDR_NONE){
		struct hostent *he;		//主机信息

		if((he=gethostbyname(argv[DST_IP]))==NULL){
			fprintf(stderr,"gethostbyname error\n");
			exit(EXIT_FAILURE);
		}
		memcpy((char *)&dst_ip,(char *)he->h_addr,sizeof(he->h_addr));
	}

	//检索服务器的端口号
	if(argc==3){
		if((port=atoi(argv[DST_PORT]))==0){
			struct servent * se;	//服务信息

			if((se=getservbyname(argv[DST_PORT],"tcp"))!=NULL)
				port=(int) ntohs((u_short)se->s_port);
			else{
				fprintf(stderr,"getservbyname error\n");
				exit(EXIT_FAILURE);
			}
		}
	}else
		port=DEFAULT_PORT;

	//使用TCP协议打开一个套接字
	if((s=socket(AF_INET,SOCK_STREAM,0))<0){
		perror("socket");
		exit(EXIT_FAILURE);
	}

	//设定服务器的地址,建立一个连接
	memset((char *)&server,0,sizeof(server));
	server.sin_family=AF_INET;
	server.sin_addr.s_addr=dst_ip;
	server.sin_port=htons(port);
	if(connect(s,(struct sockaddr *)&server,sizeof(server))<0){
		perror("connect");
		exit(EXIT_FAILURE);
	}

	printf("Connected to '%s'\n",inet_ntoa(server.sin_addr));

	//客户机处理的主要子程序
	while(1){
		//select超时的设定
		tv.tv_sec=600;
		tv.tv_usec=0;

		//标准输入,有无来自服务器的报文
		FD_ZERO(&readfd);
		FD_SET(0,&readfd);
		FD_SET(s,&readfd);
		if((select(s+1,&readfd,NULL,NULL,&tv))<=0){
			fprintf(stderr,"\nTimeout\n");
			break;
		}

		//标准输入
		if(FD_ISSET(0,&readfd)){
			if((n=read(0,buf,BUFSIZE-1))<=0)
				break;
			buf[n]='\n';
			sscanf(buf,"%s",cmd);
			if(strcmp(cmd,"quit")==0)
				break;
			if(send(s,buf,n,0)<=0)
				break;
		}

		//服务器
		if(FD_ISSET(s,&readfd)){
			if((n=recv(s,buf,BUFSIZE-1,0))<=0){
				fprintf(stderr,"connection closed.\n");
				exit(EXIT_FAILURE);
			}
			buf[n]='\0';
			printf("%s",buf);
			fflush(stdout);
		}
	}

	strcpy(buf,"quit");
	send(s,buf,n,0);
	close(s);

	return EXIT_SUCCESS;
}


/********************************************************
* server.c
* 服务器端程序
*********************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<netdb.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>

#define BUFSIZE 8192
#define DEFAULT_PORT 5320

enum{CMD_NAME,SRC_PORT};

int execute(char *command,char *buf,int bufmax);

int main(int argc,char *argv[])
{
	struct sockaddr_in server;	//服务器地址
	struct sockaddr_in client;	//客户机地址
	int len;	//sockaddr_in的长度
	int port;	//服务器端口号
	int s;	//接收报文用描述符
	int s0;	//接收连接用描述符
	int cn;	//接收命令的字数
	int sn;	//发送报文的字节数
	int rn;	//接收报文的字节数
	char cmd1[BUFSIZE];	//第一个语句命令
	char cmd2[BUFSIZE];	//第二个语句命令
	char recv_buf[BUFSIZE];	//接收缓冲区
	char send_buf[BUFSIZE];	//发送缓冲区
	
	//实际参数的处理(端口号)
	if(argc==2){
		if((port=atoi(argv[SRC_PORT]))==0){
			struct servent *se;	//服务信息

			if((se=getservbyname(argv[SRC_PORT],"tcp"))!=NULL)
				port=(int) ntohs((u_short)se->s_port);
			else{
				fprintf(stderr,"getservbyname error\n");
				exit(EXIT_FAILURE);
			}
		}
	}else
		port=DEFAULT_PORT;

	//使用TCP协议打开一个套接字
	if((s0=socket(AF_INET,SOCK_STREAM,0))<0){
		perror("socket");
		exit(EXIT_FAILURE);
	}

	//设定服务器地址
	memset((char *)&server,0,sizeof(server));
	server.sin_family=AF_INET;
	server.sin_addr.s_addr=htonl(INADDR_ANY);
	server.sin_port=htons(port);
	if(bind(s0,(struct sockaddr *)&server,sizeof(server))<0){
		perror("bind");
		exit(EXIT_FAILURE);
	}

	//开始接受建立连接请求
	listen(s0,5);

	//接收连接循环
	while(1){
		//接收连接处理
		len=sizeof(client);
		if((s=accept(s0,(struct sockaddr *)&client,&len))<0){
			perror("accept");
			exit(EXIT_FAILURE);
		}
		printf("Connected From '%s'\n",inet_ntoa(client.sin_addr));

#ifdef FORK_SERVER
		if(fork()!=0){
			close(s);
			continue;
		}
		close(s0);
#endif
		//服务器处理的主要子程序
		while(1){

			int i=0;	//接收字符的计数器

			sn=sprintf(send_buf,"TCP>");
			send(s,send_buf,sn,0);

receive:	//流型数据的接收处理
			if((rn=recv(s,&recv_buf[i],1,0))<0)
				break;

			//以换行为单位进行接收处理
			if(recv_buf[i]!='\n'){
				i++;
				if(i<BUFSIZE-1)
					goto receive;
			}
			recv_buf[i]='\0';
			printf("receive '%s'\n",recv_buf);

			//接收命令的处理
			if((cn=sscanf(recv_buf,"%s%s",cmd1,cmd2))<=0)
				continue;
			else if(cn==2 && strcmp(cmd1,"show")==0){
				if(strcmp(cmd2,"route")==0)
#ifdef _linux
					sn=execute("/usr/bin/netstat -rn",send_buf,BUFSIZE);
#else
					sn=execute("/bin/netstat -rn",send_buf,BUFSIZE);
#endif
				else if(strcmp(cmd2,"arp")==0)
#ifdef _linux
					sn=execute("/usr/sbin/arp -an",send_buf,BUFSIZE);
#else
					sn=execute("/sbin/arp -an",send_buf,BUFSIZE);
#endif
				else if(strcmp(cmd2,"tcp")==0)
#ifdef _linux
					sn=execute("/usr/bin/netstat -tn",send_buf,BUFSIZE);
#else
					sn=execute("/bin/netstat -tn",send_buf,BUFSIZE);
#endif
				else if(strcmp(cmd2,"nic")==0)
					sn=execute("/sbin/ifconfig -a",send_buf,BUFSIZE);
				else
					sn=sprintf(send_buf,"parameter error '%s'\n"
					"show[route|arp|tcp|nic]\n",cmd2);
			}else if(cn==1){
				if(strcmp(cmd1,"quit")==0)
					break;
				send_buf[0]='\0';
				if(strcmp(cmd1,"help")!=0)
					sprintf(send_buf,"command error '%s'\n",cmd1);
				strcat(send_buf,"command:\n"
					"show route\n"
					"show arp\n"
					"show tcp\n"
					"show nic\n"
					"quit\n"
					"help\n");
				sn=strlen(send_buf);
			}else
				sn=sprintf(send_buf,"command error '%s'\n",cmd1);
			if(sn==0)
				sn=sprintf(send_buf,"\n");

			if(send(s,send_buf,sn,0)<0)
				break;
			printf("%s",send_buf);
		}
		printf("Connection closed.\n");
		close(s);
	}
	close(s0);

	return EXIT_SUCCESS;
}

/*
*int execute(char *command,char *buf,int bufmax);
*
*功能
*	执行命令,将结果存储到缓冲区中
*实际参数
*	char *command;	所执行的命令
*	char *buf;	存储输出结果的缓冲区
*	int bufmax	缓冲区的大小
*返回值
*	int	存储到缓冲区的字符数
*/
int execute(char *command,char *buf,int bufmax)
{
	FILE *fp;	//文件指针
	int i;		//输入数据的字节数

	if((fp=popen(command,"r"))==NULL){
		perror(command);
		i=sprintf(buf,"server error: '%s' cannot execute.\n",command);
	}else{
		i=0;
		while((buf[i]=fgetc(fp))!=EOF && i<bufmax-1)
			i++;

		pclose(fp);
	}
	return i;
}


server还是linux,如果client是windows就这么弄,(一个demo~~自己视情况改改吧):server.c代码不变)

#include <stdio.h>  
#include <Winsock2.h>  

#pragma comment( lib, "ws2_32.lib" ) 

#define  SVR_ADDR "172.18.131.241"
#define  SVR_PORT 5320

void main()
{
	WSADATA wsaData;  

	if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0 ) 
	{  
		return;  
	}  

	SOCKET sock_id=socket(AF_INET,SOCK_STREAM,0);  
	if ( sock_id == INVALID_SOCKET )
	{
		printf("socket error.\n");
		return;
	}

	SOCKADDR_IN addr_svr;  
	int addrlen=sizeof(struct sockaddr_in);
	memset(&addr_svr, 0,addrlen);
	addr_svr.sin_family=AF_INET;
	addr_svr.sin_addr.s_addr=inet_addr(SVR_ADDR);
	addr_svr.sin_port=htons(SVR_PORT);

	if(connect(sock_id,(SOCKADDR*)&addr_svr,sizeof(SOCKADDR)) != 0){
		printf("connect error.\n");
		return;
	}
	
	char buf[100];
	int bufLen = 100;

	fd_set readfd;
	int s=0;
	int n=0;
	struct timeval tv;
	int BUFSIZE = 64;

	while(true)
	{
		if((n=recv(sock_id,buf,BUFSIZE-1,0))<=0){  
			fprintf(stderr,"connection closed.\n");  
			exit(EXIT_FAILURE);  
		}  
		buf[n]='\0';  
		printf("%s",buf);  
		fflush(stdout);  

		strcpy(buf,"/bin/netstat -rn\n");
		int len = strlen(buf);
		if(send(sock_id,buf,len,0)<=0)  
			break;  

	}
	
	closesocket(sock_id);

}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值