前言
我:“师弟,review完你的代码之后,你觉得有没有什么地方可以优化?”
师弟一脸懵。
我:“比如,你把客户端和服务端的可执行文件生成之后,我把服务端部署到我的测试机器上,客户端部署在另一台机器上,这样可行么?”
师弟:“师兄你这么说,那就是不可行了?”
我:“为什么不可行呢?”
师弟:“我先测试一下。”
十几分钟过后,师弟过来说,“的确不行,每次服务端的部署位置改变,客户端就出现连不上服务端的情况,主要是因为客户端中的server ip是固定的。除非重新修改客户端代码中的ip。”
我:“如果每次更换部署的服务器,都需要重新修改一次代码,再重新编译,是不是很麻烦?”
师弟:“是有点。我想想怎么优化一下。”
方式一 main函数传参
客户端程序,可以通过main函数传参的形式,带入ip,这样client运行方式,就变为了如下方式,可以灵活设置要连接的服务端的ip。
./client 127.0.0.1
完整代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#define PORT 8080
#define BUF_SIZE 1024
int main(int argc, char *argv[])
{
int sock = 0;
struct sockaddr_in serv_addr;
char buffer[BUF_SIZE] = {0};
if (argc != 2) {//参数解析
printf("Help: %s ip!\n", argv[0]);
return -1;
}
// Create a socket
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("Socket creation error!\n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0) {
printf("Invalid address/ Address not supported!\n");
return -1;
}
// Connect to the server
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
printf("Connection Failed!\n");
return -1;
}
while (1) {
memset(buffer, 0, BUF_SIZE);
// Read data from the server
read(sock, buffer, BUF_SIZE);
printf("%s", buffer);
if (strcmp(buffer, "Exit") == 0) {
printf("\nNormal Exit, bye!\n");
break;
}
// Send data to the server
scanf("%s", buffer);
send(sock, buffer, strlen(buffer), 0);
}
close(sock);
return 0;
}
int main(int argc, char *argv[])
参数说明:
第一个参数:argc表示传入参数的个数
第二个参数:argv是字符串数组,用来存放指向字符串参数的指针数组,每一个元素指向一个参数。各成员含义如下:
argv[0]:指向程序运行的名称。
argv[1]:指向第一个参数。
argv[2]:指向第二个参数。
…
argv[n]:指向第n个参数。
规定:argv[n]为NULL时,表示参数的结尾。
以 ./client 11 22 33为例说明如下:
方式二 读取配置文件的形式
实现略
总结
对比两种方式,以main函数传参实现较为简单一些。在程序设计时候,需要时刻考虑程序的易用性,一个好用的系统,不只是功能完备就够的,好用也是关键。