Tcp 服务端问题? tcp (同步)服务端 为什么会接收不到数据?客户端发送无异常,重启程序后就可以了 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);Socket client;private void SocketReceivedata() { int port = 8888; string recvdata = string.Empty;//接受的数据 string senddata = string.Empty;//发送数据 string ipstr = string.Empty; byte[] data = new byte[20 * 1024];//用于缓存客户端所发送的信息,通过socket传递的信息必须为字节数组 int recv;//用于表示客户端发送的信息长度 IPEndPoint ipep = new IPEndPoint(IPAddress.Any, port);//本机预使用的IP和端口 newsock.Bind(ipep);//绑定 newsock.Listen(10);//监听 try { while (true) { //用死循环来不断的从客户端获取信息 //data=new byte[20*1024]; client = newsock.Accept(); IPEndPoint clientip = (IPEndPoint)client.RemoteEndPoint; if (client.Connected) { while (true) { byte[] sdata = new byte[10 * 1024]; recv = client.Receive(data); if (recv == 0)//当信息长度为0,说明客户端连接断开 break; recvdata = Encoding.UTF8.GetString(data, 0, recv); senddata = "ok"; sdata = Encoding.UTF8.GetBytes(senddata); client.Send(sdata, sdata.Length, SocketFlags.None); Writetext(recvdata, clientip.Address.ToString()); } } } } catch (SocketException) { return; } } 我记得我是在书上看到的,没有实际试过。调试这种程序最好是客户端服务器分别在2台pc机上。 if (recv == 0)//当信息长度为0,说明客户端连接断开 break;如果两者都在一台机子上客户端断开连接貌似recv 不会等于0.所以不会跳出循环。LZ可以试一下,然后说一下结论。我也想知道书上说的对不对。 if (client.Connected)这句你能断定为真吗如果不为真,那么你怎么可能接受到数据呢 这是CSDN上看到的,希望对楼主有所帮助Socket的Send,Recv的长度问题:一个包没有固定长度,以太网限制在46-1500字节,1500就是以太网的MTU,超过这个量,TCP会为IP数据报设置偏移量进行分片传输,现在一般可允许应用层设置8k(NTFS系统)的缓冲区,8k的数据由底层分片,而应用层看来只是一次发送。 windows的缓冲区经验值是4k。 Socket本身分为两种,流(TCP)和数据报(UDP),你的问题针对这两种不同使用而结论不一样。甚至还和你是用阻塞、还是非阻塞Socket来编程有关。 1、通信长度,这个是你自己决定的,没有系统强迫你要发多大的包,实际应该根据需求和网络状况来决定。对于TCP,这个长度可以大点,但要知道,Socket内部默认的收发缓冲区大小大概是8K,你可以用SetSockOpt来改变。但对于UDP,就不要太大,一般在1024至10K。注意一点,你无论发多大的包,IP层和链路层都会把你的包进行分片发送,一般局域网就是1500左右,广域网就只有几十字节。分片后的包将经过不同的路由到达接收方,对于UDP而言,要是其中一个分片丢失,那么接收方的IP层将把整个发送包丢弃,这就形成丢包。显然,要是一个UDP发包佷大,它被分片后,链路层丢失分片的几率就佷大,你这个UDP包,就佷容易丢失,但是太小又影响效率。最好可以配置这个值,以根据不同的环境来调整到最佳状态。 send()函数返回了实际发送的长度,在网络不断的情况下,它绝不会返回(发送失败的)错误,最多就是返回0。对于TCP你可以写一个循环发送。当 send函数返回SOCKET_ERROR时,才标志着有错误。但对于UDP,你不要写循环发送,否则将给你的接收带来极大的麻烦。所以UDP需要用 SetSockOpt来改变Socket内部Buffer的大小,以能容纳你的发包。明确一点,TCP作为流,发包是不会整包到达的,而是源源不断的到,那接收方就必须组包。而UDP作为消息或数据报,它一定是整包到达接收方。 2、关于接收,一般的发包都有包边界,首要的就是你这个包的长度要让接收方知道,于是就有个包头信息,对于TCP,接收方先收这个包头信息,然后再收包数据。一次收齐整个包也可以,可要对结果是否收齐进行验证。这也就完成了组包过程。UDP,那你只能整包接收了。要是你提供的接收Buffer过小,TCP 将返回实际接收的长度,余下的还可以收,而UDP不同的是,余下的数据被丢弃并返回WSAEMSGSIZE错误。注意TCP,要是你提供的Buffer佷大,那么可能收到的就是多个发包,你必须分离它们,还有就是当Buffer太小,而一次收不完Socket内部的数据,那么Socket接收事件 (OnReceive),可能不会再触发,使用事件方式进行接收时,密切注意这点。这些特性就是体现了流和数据包的区别。 补充一点,接收BuffSize >= 发送BuffSize >= 实际发送Size,对于内外部的Buffer都适用,上面讲的主要是Socket内部的Buffer大小关系。 3、TCP是有多少就收多少,如果没有当然阻塞Socket的recv就会等,直到有数据,非阻塞Socket不好等,而是返回 WSAEWOULDBLOCK。UDP,如果没有数据,阻塞Socket就会等,非阻塞Socket也返回WSAEWOULDBLOCK。如果有数据,它是会等整个发包到齐,并接收到整个发包,才返回。 [color=#FF6600我现在的问题是这样我只做服务端,对方是客户端出现问题:1.有时候接收不到数据,可对方发送数据正常,会是什么问题?2.对方客户端接收数据有重复(收到两条记录,且第一调记录有点乱),是服务端问题呢,还是客户端问题?还有就是 总感觉上面的代码有问题 可就不知道如何改[/color] 对方发送数据正常???接受不到有可能是客户端发送失败也有可能服务器端发送失败还有tcp是要三握手的你服务器端要返回客户端信息,否则 客户端过些时候接受不到服务器端的信息,连接 就会失效。按你现在的状态感觉应该是客户端的问题。而不是服务器端的问题。 如果对方一下子发送10241个字节怎么办?另外所谓的“沾包”是很正常的,你的一次receive里可能有对方两个发送的消息,甚至更多次的消息;甚至buffer的开始不是一个消息的开头,因为上一次Receive没有穷见所有数据(即使对方法的消息很小,但是还有算上沾包的),此时消息内容就跨前后两次Receive的边界里边。 找一个真正做过产品的人面对面实际去问问吧。这种东西,不是从网上抄点文章,就能做起来的。网上的文章可以执行,但是往往执行它的人都找个借口:“嗯,如果消息发送快了,或者内容大了,我还不行。但是小的我已经行了!”。其实产品代码根本不是弄一个winform程序对另外一个winform程序发点demo数据的网上程序那样写的。 TCP 是基于流的协议。。所以需要自行定义封包格式。最简单的是发送的时候在封包头部加上长度,读取是根据长度截取。就不会出现丢信息的现象。再者 TCP 是面向连接的协议,所以出现的一切数据读取问题都是程序问题不可能是网络问题。不过。。好多写出非常烂的网络发送程序的人,都拒绝承认这个事实 winform读取电子磅秤数据 【寻求帮助】:如何查找指定的字符串是否在.txt文件中!!! VS中两个项目合并 【请教】程序不能于原目录运行 简单问题String.Format(@" select * from tab") oracle连接问题。 c# 如何利用flash.ocx 控件播放flash 如何实现刷新 树的问题 如何禁止一个控件重绘? 代替复制的问题?急!!!! 急急急,大牛们帮帮小弟,关于post请求
Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Socket client;
private void SocketReceivedata()
{
int port = 8888;
string recvdata = string.Empty;//接受的数据
string senddata = string.Empty;//发送数据
string ipstr = string.Empty;
byte[] data = new byte[20 * 1024];//用于缓存客户端所发送的信息,通过socket传递的信息必须为字节数组 int recv;//用于表示客户端发送的信息长度
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, port);//本机预使用的IP和端口
newsock.Bind(ipep);//绑定
newsock.Listen(10);//监听
try
{
while (true)
{
//用死循环来不断的从客户端获取信息
//data=new byte[20*1024];
client = newsock.Accept();
IPEndPoint clientip = (IPEndPoint)client.RemoteEndPoint;
if (client.Connected)
{
while (true)
{
byte[] sdata = new byte[10 * 1024];
recv = client.Receive(data); if (recv == 0)//当信息长度为0,说明客户端连接断开
break;
recvdata = Encoding.UTF8.GetString(data, 0, recv);
senddata = "ok"; sdata = Encoding.UTF8.GetBytes(senddata);
client.Send(sdata, sdata.Length, SocketFlags.None);
Writetext(recvdata, clientip.Address.ToString());
}
}
}
}
catch (SocketException)
{
return;
}
}
调试这种程序最好是客户端服务器分别在2台pc机上。
if (recv == 0)//当信息长度为0,说明客户端连接断开
break;
如果两者都在一台机子上客户端断开连接貌似recv 不会等于0.
所以不会跳出循环。
LZ可以试一下,然后说一下结论。我也想知道书上说的对不对。
这句你能断定为真吗
如果不为真,那么你怎么可能接受到数据呢
windows的缓冲区经验值是4k。
Socket本身分为两种,流(TCP)和数据报(UDP),你的问题针对这两种不同使用而结论不一样。甚至还和你是用阻塞、还是非阻塞Socket来编程有关。
1、通信长度,这个是你自己决定的,没有系统强迫你要发多大的包,实际应该根据需求和网络状况来决定。对于TCP,这个长度可以大点,但要知道,Socket内部默认的收发缓冲区大小大概是8K,你可以用SetSockOpt来改变。但对于UDP,就不要太大,一般在1024至10K。注意一点,你无论发多大的包,IP层和链路层都会把你的包进行分片发送,一般局域网就是1500左右,广域网就只有几十字节。分片后的包将经过不同的路由到达接收方,对于UDP而言,要是其中一个分片丢失,那么接收方的IP层将把整个发送包丢弃,这就形成丢包。显然,要是一个UDP发包佷大,它被分片后,链路层丢失分片的几率就佷大,你这个UDP包,就佷容易丢失,但是太小又影响效率。最好可以配置这个值,以根据不同的环境来调整到最佳状态。
send()函数返回了实际发送的长度,在网络不断的情况下,它绝不会返回(发送失败的)错误,最多就是返回0。对于TCP你可以写一个循环发送。当 send函数返回SOCKET_ERROR时,才标志着有错误。但对于UDP,你不要写循环发送,否则将给你的接收带来极大的麻烦。所以UDP需要用 SetSockOpt来改变Socket内部Buffer的大小,以能容纳你的发包。明确一点,TCP作为流,发包是不会整包到达的,而是源源不断的到,那接收方就必须组包。而UDP作为消息或数据报,它一定是整包到达接收方。
2、关于接收,一般的发包都有包边界,首要的就是你这个包的长度要让接收方知道,于是就有个包头信息,对于TCP,接收方先收这个包头信息,然后再收包数据。一次收齐整个包也可以,可要对结果是否收齐进行验证。这也就完成了组包过程。UDP,那你只能整包接收了。要是你提供的接收Buffer过小,TCP 将返回实际接收的长度,余下的还可以收,而UDP不同的是,余下的数据被丢弃并返回WSAEMSGSIZE错误。注意TCP,要是你提供的Buffer佷大,那么可能收到的就是多个发包,你必须分离它们,还有就是当Buffer太小,而一次收不完Socket内部的数据,那么Socket接收事件 (OnReceive),可能不会再触发,使用事件方式进行接收时,密切注意这点。这些特性就是体现了流和数据包的区别。
补充一点,接收BuffSize >= 发送BuffSize >= 实际发送Size,对于内外部的Buffer都适用,上面讲的主要是Socket内部的Buffer大小关系。
3、TCP是有多少就收多少,如果没有当然阻塞Socket的recv就会等,直到有数据,非阻塞Socket不好等,而是返回 WSAEWOULDBLOCK。UDP,如果没有数据,阻塞Socket就会等,非阻塞Socket也返回WSAEWOULDBLOCK。如果有数据,它是会等整个发包到齐,并接收到整个发包,才返回。
我只做服务端,对方是客户端
出现问题:
1.有时候接收不到数据,可对方发送数据正常,会是什么问题?
2.对方客户端接收数据有重复(收到两条记录,且第一调记录有点乱),是服务端问题呢,还是客户端问题?还有就是 总感觉上面的代码有问题 可就不知道如何改[/color]
接受不到有可能是客户端发送失败也有可能服务器端发送失败
还有tcp是要三握手的你服务器端要返回客户端信息,否则 客户端过些时候接受不到服务器端的信息,连接 就会失效。
按你现在的状态感觉应该是客户端的问题。而不是服务器端的问题。
如果对方一下子发送10241个字节怎么办?另外所谓的“沾包”是很正常的,你的一次receive里可能有对方两个发送的消息,甚至更多次的消息;甚至buffer的开始不是一个消息的开头,因为上一次Receive没有穷见所有数据(即使对方法的消息很小,但是还有算上沾包的),此时消息内容就跨前后两次Receive的边界里边。