Socket Server指定监听端口和IP
TCP/IP进行网络编程时,会用到socket相关函数,各个函数的详细介绍在这里:
https://www.cnblogs.com/liedElxa/p/10795398.html
需求描述
考虑到一种场景,在一个多网卡的服务器上,比如有10.0.0.1、10.0.0.2、10.0.0.3三个网卡都在使用,我们想做一个监听8080号端口的服务器,而且只有客户访问10.0.0.1:8080才会响应,访问10.0.0.2:8080或10.0.0.3:8080均不会收到回复。
在进行TCP/IP网络编程过程中,一般在对serv_adr进行绑定时,使用serv_adr进行绑定。
解决方式
serv_adr结构体定义如下:
struct sockaddr_in {
short int sin_family; /* 通信类型 */
unsigned short int sin_port; /* 端口 */
struct in_addr sin_addr; /* Internet 地址 */
unsigned char sin_zero[8]; /* 与sockaddr结构的长度相同*/
};
而band()函数的定义如下:
// 将一个地址和端口信息address绑定到一个socket连接上
int bind(int socket,sockaddr * address,uint addrlen);
// socket:之前创建的socket
// sockaddr:一个用来存放Ip地址和端口号的结构体
// addrlen:上述结构体的长度
// 返回值:为-1表示失败,若端口被占用,会从新绑定一个随机端口(仍返回失败)
// 地址绑定为0表示绑定本机所有IP,即INADDR_ANY(0.0.0.0)表示任何可绑定的地址
所以,我们可以通过设置serv_adr结构体的s_addr值实现指定IP(10.0.0.1)的绑定,然后再调用bind()函数,之后的逻辑不变。
memset(&serv_adr, 0, sizeof(serv_adr));
serv_adr.sin_family = AF_INET;
/* INADDR_ANY表示不管是哪个网卡接收到数据,只要目的端口是SERV_PORT,就会被该应用程序接收到 */
//serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_adr.sin_addr.s_addr = inet_addr("10.0.0.1");
serv_adr.sin_port = htons(8080);
//分配地址接受数据,不限制数据传输对象
if (bind(serv_sock, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) == -1)
error_handling("bind() error");
之后的编程流程不变。