套接字网络编程笔记

本文详细解析了套接字网络编程的核心概念,包括发送和接收数据包的方法、TCP连接原理、阻塞套接字操作、互答通信模式、字节顺序以及网络连接状态监控。重点介绍了如何通过定义报文头和应用层协议来确保数据完整传输,以及在多线程环境下高效处理通信任务。

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

套接字网络编程笔记

1.调用int send( __in  SOCKET s, __in  const char* buf, __in  int len, __in  int flags); 发出的数据包,在传送过程中,虽然顺序不会把打乱,但可能会拆分成多个包,这样,只调用一次int recv( __in   SOCKET s, __out  char* buf, __in   int len, __in   int flags); 可能不能被完整地接收。

解决的方法是,定义TCP之上的协议,即应用层协议,指示数据包长度。最简单的实现为:

void SendFn(SOCKET s, char* data, int len)
{
	char* buff = (char*)malloc(sizeof(int)+len);

	//填充报文头
	int* pLen = (int*)buff;
	*pLen = len;

	//填充有效数据
	memcpy(buff+sizeof(int), data, len);

	send(s, buff, sizeof(int)+len, 0);
}

//完整接收指定长度数据包
void RecvFnS(SOCKET s, char* buff, int len)
{
	int done = 0;
	done = recv(s, buff, len, 0);

	while ( done < len )
		done += recv(s, buff+done, len, 0);
}

void RecvFn(SOCKET s)
{
	int len;
	//接收报文头
	RecvFnS(s, (char*)&len, sizeof(int));

	//接收有效数据
	if ( len > 0 )
	{	
		char* buff = (char*)malloc(len);
		RecvFnS(s, buff, len);
	}
}

2.TCP 通信时,服务器用 SOCKET accept( __in     SOCKET s, __out    struct sockaddr* addr, __inout  int* addrlen);  创建的套接字共同占用一个端口,即服务器监听端口。

为什么要这么做:客服端套接字指定通信对方的端口就是监听端口,没有理由找一个使用其它端口的套接字跟它连接。

为什么能这么做:TCP报文中,包含源端口,与目标端口,再加上IP层的源IP地址及目标IP地址,这四个信息,就是运输层多路分解中,所需要的四元组,意思是可以唯一确定一个TCP连接。当从IP层,解包数据后,就可以根据四元组,找到这些数据的目标TCP连接。这点跟UDP连接是有区别的,因为UDP多路分解时只使用目标IP地址及目标端口,所以,只要目标IP为本机IP,目标端口为监听端口的,UDP连接都会定向到一个UPD连接。这意味,UDP是一个一对多的连接(确切地说UPD不能叫连接)。

3.阻塞套接字可以在recv的同时,调用send

4.互答通信模式(时间紧,未仔细考虑非阻塞模式)。互答通信指的是,双方都可能主动地向对方发请求。这意味着双方都必须实时监听着对方的请求。监听是会阻塞线程的,所以程序不可能是单线的(罗云彬书上聊天室例子介绍了互答通信的解决方案,而且用的是单线程, 但其实在模拟多线程,而且在多回合会话中,整个流程很难被维护)。再考虑如何使用连接。同一个套接字虽然可以在recv同时调用send,但不能同时调用recv,因为多个线程会抢夺数据,导致混乱。只使用一个套接字,这种情况是会发生的,比如,监听线程调用recv堵在那时,其它线程调用send后,又用recv来等待对方的回应,这时就有冲突了。所以套接字至少要有两个。一个用于被动会话(监听),一个用于主动会话。

5.SOCKET类型是一个句柄,有点指针的性质,并且accept会分配SOCKET对象,所以可以看成在堆上的指针,直接传给新线程当参数:

		client = ::accept(s, (SOCKADDR*)&remoteAddr, &nAddrLen);
		if(client == INVALID_SOCKET)
			continue;
		_beginthreadex(NULL, NULL, SServerThread, &client, NULL, NULL);//不存在缺陷,因为SOCKET是句柄,相当于指针,typedef UINT_PTR        SOCKET;

6.字节顺序。只有与网络协议栈本身的数据的字节顺序是与主机的相反的,自己的数据,发送出去是什么样,接受后就是什么样。字节倒序,是以字节为单位:如 0x1234 倒序后成 0x3412

7.Win+R运行perfmon.msc可以查看网络连接状况。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值