socket网络编程实现tcpserver和tcpclient,并使用配置文件配置ip地址和port端口进行通信

socket网络编程

面向套接字通信过程属于最基础的网络通信,本程序的特殊是使用通过配置文件的方式来配置服务器客户端的ip地址和端口演示程序如下所示。本程序使用的配置文件形式为.conf格式的,当然也可以采用.txt格式的配置文件。

使用方法:分别将两个代码gcc编译完成后,开两个终端,分别启动服务器和客户端则可实现通信。

服务器端先启动进行socket,bind,listen,accept等工作,客户端请求连接socket,connect。建立连接后进行服务请求和应答,执行相关发送和接受的操作,最后关闭文件描述符,完成通信。

配置文件完整代码
cls.conf

[cls_server]    
#配置文件等号左右可以有空格也可以没有    
ip=127.0.0.1
port=5566

服务器端完整代码
tcpserv.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <wait.h>
#include <errno.h>
#include <ctype.h>
#include <assert.h>    
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define KEYVALLEN 256

/*   删除左边的空格   */
char * l_trim(char * szOutput, const char *szInput);

/*   删除右边的空格   */
char *r_trim(char *szOutput, const char *szInput);

/*   删除两边的空格   */
char * a_trim(char * szOutput, const char * szInput);


int GetProfileString(char *profile, char *AppName, char *KeyName, char *KeyVal );    
/*   删除左边的空格   */    
char * l_trim(char * szOutput, const char *szInput)    
{    
	assert(szInput != NULL);    
	assert(szOutput != NULL);    
	assert(szOutput != szInput);    
	for   (NULL; *szInput != '\0' && isspace(*szInput); ++szInput){    
		;    
	}    
	return strcpy(szOutput, szInput);    
}    

/*   删除右边的空格   */    
char *r_trim(char *szOutput, const char *szInput)    
{    
	char *p = NULL;    
	assert(szInput != NULL);    
	assert(szOutput != NULL);    
	assert(szOutput != szInput);    
	strcpy(szOutput, szInput);    
	for(p = szOutput + strlen(szOutput) - 1; p >= szOutput && isspace(*p); --p){    
		;    
	}    
	*(++p) = '\0';    
	return szOutput;    
}    

/*   删除两边的空格   */    
char * a_trim(char * szOutput, const char * szInput)    
{    
	char *p = NULL;    
	assert(szInput != NULL);    
	assert(szOutput != NULL);    
	l_trim(szOutput, szInput);    
	for   (p = szOutput + strlen(szOutput) - 1;p >= szOutput && isspace(*p); --p){    
		;    
	}    
	*(++p) = '\0';    
	return szOutput;    
}    


int GetProfileString(char *profile, char *AppName, char *KeyName, char *KeyVal )    
{    
	char appname[32],keyname[32];    
	char *buf,*c;    
	char buf_i[KEYVALLEN], buf_o[KEYVALLEN];    
	FILE *fp;    
	int found=0; /* 1 AppName 2 KeyName */    
	if( (fp=fopen( profile,"r" ))==NULL ){    
		printf( "openfile [%s] error [%s]\n",profile,strerror(errno) );    
		return(-1);    
	}    
	fseek( fp, 0, SEEK_SET );    
	memset( appname, 0, sizeof(appname) );    
	sprintf( appname,"[%s]", AppName );    

	while( !feof(fp) && fgets( buf_i, KEYVALLEN, fp )!=NULL ){    
		l_trim(buf_o, buf_i);    
		if( strlen(buf_o) <= 0 )    
			continue;    
		buf = NULL;    
		buf = buf_o;    

		if( found == 0 ){    
			if( buf[0] != '[' ) {    
				continue;    
			} else if ( strncmp(buf,appname,strlen(appname))==0 ){    
				found = 1;    
				continue;    
			}    

		} else if( found == 1 ){    
			if( buf[0] == '#' ){    
				continue;    
			} else if ( buf[0] == '[' ) {    
				break;    
			} else {    
				if( (c = (char*)strchr(buf, '=')) == NULL )    
					continue;    
				memset( keyname, 0, sizeof(keyname) );    

				sscanf( buf, "%[^=|^ |^\t]", keyname );    
				if( strcmp(keyname, KeyName) == 0 ){    
					sscanf( ++c, "%[^\n]", KeyVal );    
					char *KeyVal_o = (char *)malloc(strlen(KeyVal) + 1);    
					if(KeyVal_o != NULL){    
						memset(KeyVal_o, 0, sizeof(KeyVal_o));    
						a_trim(KeyVal_o, KeyVal);    
						if(KeyVal_o && strlen(KeyVal_o) > 0)    
							strcpy(KeyVal, KeyVal_o);    
						free(KeyVal_o);    
						KeyVal_o = NULL;    
					}    
					found = 2;    
					break;    
				} else {    
					continue;    
				}    
			}    
		}    
	}    
	fclose( fp );    
	if( found == 2 )    
		return(0);    
	else    
		return(-1);    
}    

int main(void) {
	
	char ip[16];
	char port[16];
	GetProfileString("./cls.conf", "cls_server", "ip", ip);
	GetProfileString("./cls.conf", "cls_server", "port", port);

    printf("服务器:创建网络套接字\n");
    int sockfd = socket(PF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket");
        return -1;
    }
    printf("服务器:准备地址并绑定\n");
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(atoi(port));
    addr.sin_addr.s_addr = INADDR_ANY;
    if (bind(sockfd, (struct sockaddr*)&addr,
        sizeof(addr)) == -1) {
        perror("bind");
        return -1;
    }
    printf("服务器:侦听套接字\n");
    if (listen(sockfd, 1024) == -1) {
        perror("listen");
        return -1;
    }
    for (;;) {
        printf("服务器:等待连接\n");
        struct sockaddr_in addrcli = {};
        socklen_t addrlen = sizeof(addrcli);
        int connfd = accept(sockfd,
            (struct sockaddr*)&addrcli,
            &addrlen);
        if (connfd == -1) {
            perror("accept");
            return -1;
        }
        printf("服务器:客户机%s:%u\n",
            inet_ntoa(addrcli.sin_addr),
            ntohs(addrcli.sin_port));
       
        for (;;) {
        char buf[1024];
        ssize_t rb = recv(connfd, buf,
            sizeof(buf), 0);
        if (rb == -1) {
            perror("recv");
            return -1;
        }
         if (! strcmp(buf, "!\n"))
            break;
        printf("< %s", buf);
    
        printf("%d:发送响应\n", getpid());
        if (send(connfd, buf, rb, 0) == -1) {
            perror("send");
            return -1;
        }
    }

        if (close(connfd) == -1) {
            perror("close");
            return -1;
        }
    }
    return 0;
}

客户端完整代码
tcpcli.c

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

#define KEYVALLEN 256

/*   删除左边的空格   */
char * l_trim(char * szOutput, const char *szInput);

/*   删除右边的空格   */
char *r_trim(char *szOutput, const char *szInput);

/*   删除两边的空格   */
char * a_trim(char * szOutput, const char * szInput);


int GetProfileString(char *profile, char *AppName, char *KeyName, char *KeyVal );    
/*   删除左边的空格   */    
char * l_trim(char * szOutput, const char *szInput)    
{    
	assert(szInput != NULL);    
	assert(szOutput != NULL);    
	assert(szOutput != szInput);    
	for   (NULL; *szInput != '\0' && isspace(*szInput); ++szInput){    
		;    
	}    
	return strcpy(szOutput, szInput);    
}    

/*   删除右边的空格   */    
char *r_trim(char *szOutput, const char *szInput)    
{    
	char *p = NULL;    
	assert(szInput != NULL);    
	assert(szOutput != NULL);    
	assert(szOutput != szInput);    
	strcpy(szOutput, szInput);    
	for(p = szOutput + strlen(szOutput) - 1; p >= szOutput && isspace(*p); --p){    
		;    
	}    
	*(++p) = '\0';    
	return szOutput;    
}    

/*   删除两边的空格   */    
char * a_trim(char * szOutput, const char * szInput)    
{    
	char *p = NULL;    
	assert(szInput != NULL);    
	assert(szOutput != NULL);    
	l_trim(szOutput, szInput);    
	for   (p = szOutput + strlen(szOutput) - 1;p >= szOutput && isspace(*p); --p){    
		;    
	}    
	*(++p) = '\0';    
	return szOutput;    
}    


int GetProfileString(char *profile, char *AppName, char *KeyName, char *KeyVal )    
{    
	char appname[32],keyname[32];    
	char *buf,*c;    
	char buf_i[KEYVALLEN], buf_o[KEYVALLEN];    
	FILE *fp;    
	int found=0; /* 1 AppName 2 KeyName */    
	if( (fp=fopen( profile,"r" ))==NULL ){    
		printf( "openfile [%s] error [%s]\n",profile,strerror(errno) );    
		return(-1);    
	}    
	fseek( fp, 0, SEEK_SET );    
	memset( appname, 0, sizeof(appname) );    
	sprintf( appname,"[%s]", AppName );    

	while( !feof(fp) && fgets( buf_i, KEYVALLEN, fp )!=NULL ){    
		l_trim(buf_o, buf_i);    
		if( strlen(buf_o) <= 0 )    
			continue;    
		buf = NULL;    
		buf = buf_o;    

		if( found == 0 ){    
			if( buf[0] != '[' ) {    
				continue;    
			} else if ( strncmp(buf,appname,strlen(appname))==0 ){    
				found = 1;    
				continue;    
			}    

		} else if( found == 1 ){    
			if( buf[0] == '#' ){    
				continue;    
			} else if ( buf[0] == '[' ) {    
				break;    
			} else {    
				if( (c = (char*)strchr(buf, '=')) == NULL )    
					continue;    
				memset( keyname, 0, sizeof(keyname) );    

				sscanf( buf, "%[^=|^ |^\t]", keyname );    
				if( strcmp(keyname, KeyName) == 0 ){    
					sscanf( ++c, "%[^\n]", KeyVal );    
					char *KeyVal_o = (char *)malloc(strlen(KeyVal) + 1);    
					if(KeyVal_o != NULL){    
						memset(KeyVal_o, 0, sizeof(KeyVal_o));    
						a_trim(KeyVal_o, KeyVal);    
						if(KeyVal_o && strlen(KeyVal_o) > 0)    
							strcpy(KeyVal, KeyVal_o);    
						free(KeyVal_o);    
						KeyVal_o = NULL;    
					}    
					found = 2;    
					break;    
				} else {    
					continue;    
				}    
			}    
		}    
	}    
	fclose( fp );    
	if( found == 2 )    
		return(0);    
	else    
		return(-1);    
}    

int main(void) {

	char ip[16];    
	char port[16];
	GetProfileString("./cls.conf", "cls_server", "ip", ip);    
	GetProfileString("./cls.conf", "cls_server", "port", port);    

    printf("客户机:创建网络套接字\n");
    int sockfd = socket(PF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket");
        return -1;
    }
    printf("客户机:准备地址并连接\n");
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(atoi(port));
    addr.sin_addr.s_addr = inet_addr(ip);
    if (connect(sockfd, (struct sockaddr*)&addr,
        sizeof(addr)) == -1) {
        perror("connect");
        return -1;
    }

    for (;;) {
        printf("> ");
        char buf[1024];
        fgets(buf, sizeof(buf) / sizeof(buf[0]),
            stdin);
        if (! strcmp(buf, "!\n"))
            break;
        printf("客户机:发送请求\n");
        if (send(sockfd, buf, strlen(buf) *
            sizeof(buf[0]), 0) == -1) {
            perror("send");
            return -1;
        }
        printf("客户机:接收响应\n");
        
        ssize_t rb = recv(sockfd, buf,
            sizeof(buf) - sizeof(buf[0]), 0);
        if (rb == -1) {
            perror("recv");
            return -1;
        }

        if (rb == 0) {
            printf("客户机:服务器已关闭\n");
            break;
        }
        buf[rb / sizeof(buf[0])] = '\0';
        printf("< %s", buf);
    }

    printf("客户机:关闭套接字\n");
    if (close(sockfd) == -1) {
        perror("close");
        return -1;
    }
    printf("客户机:完成\n");
    return 0;
}

执行过程

gcc -o tcpserv tcpserv.c
gcc -o tvcpcli tcpcli.c

一个终端执行客户端,另一个终端执行服务器,则可实现。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值