getsockname和getpeername

本文介绍了TCP服务器中如何使用INADDR_ANY监听所有可用接口,并详细解释了如何通过getsockname和getpeername函数来获取服务器及客户端的真实IP地址。特别讨论了在accept前后调用这些函数的区别,并提供了一个Windows客户端的示例代码。

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

对于TCP服务器来说,如果设置的addr为INADDR_ANY,只有在accept后,用getsockname获得的者是本地分配的真实的ip,即针对已经连接的,而不是监听套接口。

用getpeername可以获取客户端的地址,虽然说,在accept时,就可以返回客户端的地址。但是当accept后,fork一个子进程,接着调用 exec时,会将返回客户地址覆盖,在这种情况下,用getpeername。

可以模拟,在windows上运行客户端程序:

#include <winsock2.h>
#include <stdio.h>
#include <string.h>

#define MAXLINE 100
#pragma comment(lib, "ws2_32.lib")

void dlg_cli(int fd)
{
	char buf[MAXLINE];
	int n;

	for (;;) {
		if (fgets(buf, MAXLINE, stdin) != NULL) {
			send(fd, buf, strlen(buf), 0);
			n = recv(fd, buf, MAXLINE, 0);
			if (n != 0) {
				buf[n] = '\0';
				puts(buf);
			}
		}
	}
}

int main(int argc, char **argv)
{
	WSADATA data;
	WORD wVersionRequested;
	int err;

	wVersionRequested = MAKEWORD(1, 1);
	err = WSAStartup(wVersionRequested, &data);
	if (err != 0) return -1;

	if (LOBYTE(data.wVersion) != 1 || HIBYTE(data.wVersion) != 1) {
		WSACleanup();
		return -1;
	}

	SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);
	SOCKADDR_IN addrSer;
	addrSer.sin_family = AF_INET;
	addrSer.sin_port = htons(9999);
	printf("addr=%s\n", argv[1]);
	addrSer.sin_addr.S_un.S_addr = inet_addr(argv[1]);
	connect(sockClient, (SOCKADDR*)&addrSer, sizeof(addrSer));

	dlg_cli(sockClient);
	closesocket(sockClient);
	WSACleanup();
	return 0;
}

注意:windows下,要加#pragma comment(lib, "ws2_32.lib"),如果不加,会提示未定义的符号之类错误

而在虚拟机中的linux下运行服务器,在accept前和后,调用getsockname,打印其分配的地址。如果创建socket时,指定的是INADDR_ANY,在accept前打印的是0.0.0.0,在accept后打印的是真实的网络接口的地址。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kgduu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值