(一)Client如何指定IP地址和端口
意义:在(0.1.0)文中,我们进行了一个Client的编程。我们知道连接服务器需要IP地址以及端口,如果我们需要连接别的服务器呢?这样IP地址和端口也需要进行相应更改。每次进行VIM编辑再编译是一件十分麻烦的事情,那么我们想在运行文件的时候就像LINUX系统下命令选项的操作进行IP地址和端口的指定。
(1)涉及函数:
1.1 getopt_long()函数
getopt_long()函数:长选项的命令行解析。
目的:就是可以指定任意IP,PORT,避免经常在文件中修改。
#include <getopt.h> //头文件包含
int getopt_long(int argc, char * const argv[],const char *optstring, const struct option *longopts,int *longindex);
参数:
argc和argv[]:用来接收main函数的参数。
optstring:一个字符串,表示可以接受的参数。例如,“a:b:cd”,表示可以接受的参数是a,b,c,d,其中,a和b参数后面跟有更多的参数值。(例如:-a host -b name)。
longopts:一个结构的实例。
longindex:表示当前长参数在longopts中的索引值。
示例:
getopt_long(argc,argv,"p:h",opts,NULL)
1.1.1 option结构体
struct option {
const char *name;
int has_arg;
int *flag;
int val;
}
`参数:
name:表示的是长参数名
has_arg(3个值):
①no_argument(或者是0),表示该参数后面不跟参数值
②required_argument(或者是1),表示该参数后面一定要跟个参数值
③optional_argument(或者是2),表示该参数后面可以跟,也可以不跟参数值
flag:用来决定,getopt_long()的返回值到底是什么。如果flag是null(通常情况),则函数会返回与该项option匹配的val值;如果flag不是NULL,则将val值赋予flag所指向的内存,并且返回值设置为0。
val:与flag联合决定返回值
示例:
struct option opts[]={
{"port",required_argument,NULL,'p'},
{"help",no_argument,NULL,'h'},
{0,0,0,0}
};
(2) Client指定IP地址和端口
因为,在Linux&Apue(0.1.0)中进行过CS的编程,这里只进行补充。
2.1 打印命令的信息让操作者了解
这里有点像Linux下的man和help。
void print_usage(char *progname)
{
printf("%s usage: \n", progname);
printf("-i(--ipaddr): sepcify server IP address\n");
printf("-p(--port): sepcify server port.\n");
printf("-h(--Help): print this help information.\n");
return ;
}
接着,在主函数中,我们需要用一个while和getopt_long函数去实现命令的获取与解析。
2.2 定义getopt_long函数需要的结构体
struct option opts[] = {
{"ipaddr", required_argument, NULL, 'i'},
{"port", required_argument, NULL, 'p'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
};
2.3 while和getop_long实命令的获取与解析
while( (ch=getopt_long(argc, argv, "i:p:h", opts, NULL)) != -1 )
{
switch(ch)
{
case 'i':
servip=optarg;
break;
case 'p':
port=atoi(optarg);
break;
case 'h':
print_usage(argv[0]);
return 0;
}
}
2.4 最后为了确保IP和端口的输入
if( !servip || !port )
{
print_usage(argv[0]);
return 0;
}
(二) Server如何听所有IP地址和指定端口
意义:同样在(0.1.0)我们编写Server服务器的时候,我们在文本中写入了IP地址和port的。但是,在实际过程中,服务器监听的端口不一定不变化的,也不可能只监听一个客户端的IP地址。所以,我们需要服务器可以随时指定端口以及监听所有IP地址。
(1)Server监听所有IP地址和指定端口
1.1 打印命令的信息让操作者了解
void print_usage(char *progname)
{
printf("%s usage: \n", progname);
printf("-p(--port): sepcify server listen port.\n");
printf("-h(--Help): print this help information.\n");
return ;
}
1.2 定义getopt_long函数需要的结构体
struct option opts[] = {
{"port", required_argument, NULL, 'p'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
};
1.3 while和getop_long实命令的获取与解析
while( (ch=getopt_long(argc, argv, "p:h", opts, NULL)) != -1 )
{
switch(ch)
{
case 'p':
port=atoi(optarg);
break;
case 'h':
print_usage(argv[0]);
return 0;
}
}
1.4 Server监听所有IP地址
在(0.1.0)文中,我们知道只需要在bind()函数中的servaddr族中进行修改即可。
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);