我正在将使用Winsock控件的旧VB6代码移植到C#.我没有做任何套接字编程,我想知道是否有人有一个很好的参考/教程/ howto,我可以用来开始加快速度.
当我继续使用我普遍没有效率的谷歌搜索时,我正在吸引蜂巢的头脑.
我目前正在使用UDP,而不是TCP.
在我的程序中,有一个线程(接收线程)负责接收来自TCP套接字的请求,并且有许多线程(工作线程)负责处理接收到的请求.处理完请求后,我需要通过TCP发送答案.
这是一个问题.我想在用于接收数据的同一个线程中发送TCP数据.接收数据后,此线程通常会等待新数据select().因此,一旦工作线程完成处理请求并将答案放入输出队列,它就必须通知接收线程有数据要发送.问题是我不知道如何取消等待select()以便离开等待和打电话send().
或者我是否应该仅使用另一个线程通过TCP发送数据?
更新
MSalters,Artyom谢谢你的答案!
MSalters,看了你的答案,我发现这个网站:Winsock 2 I/O方法和阅读WSAWaitForMultipleEvents().我的程序实际上必须在HP-UX和Windows上工作我最终决定使用Artyom建议的方法.
我正在研究一个非常大的项目,在一个文件中我们突然遇到编译时错误,编译器似乎认为我们对winsock.h bind()的调用实际上是对它的调用std::bind().似乎在包含文件中的某处有using namespace std代码片段.我们可以尝试找到它们using namespace std的使用位置并将其删除,但也许有更好的方法可以做到这一点?
"在单个Windows PC上使用UDP进行进程间通信可能会出现什么问题?" 我想......然后继续实施它.
但是尽管只发送了几百个字节并且只是非常偶发,并且尽管UDP被用作无连接协议(使用的sendto()功能),但我仍然被随机出现的错误10054 - "连接重置"所困扰.我觉得这很混乱.是吗:
我在某处读到它可能表明在另一端没有接收端口打开......但这对我来说更没意义 - 不是UDP只是假设发送数据报而不关心它发生了什么?或者在同一台机器(localhost)上的端口发送/从某些机器上的端口发送一些特殊情况?
我正在尝试使用以下代码处理Winsock_Connect事件(实际上我需要在Excel宏中使用它):
Dim Winsock1 As Winsock 'Object type definition
Sub Init()
Set Winsock1 = CreateObject("MSWinsock.Winsock") 'Object initialization
Winsock1.RemoteHost = "MyHost"
Winsock1.RemotePort = "22"
Winsock1.Connect
Do While (Winsock1.State <> sckConnected)
Sleep 200
Loop
End Sub
'Callback handler
Private Sub Winsock1_Connect()
MsgBox "Winsock1::Connect"
End Sub
Run Code Online (Sandbox Code Playgroud)
但它永远不会进入Winsock1_Connect子程序,尽管Winsock1.State是"已连接".我想使用标准MS库,因为我的PC上没有管理权限,我无法注册一些自定义库.任何人都可以告诉我,我哪里错了?
可以通过atExit函数注册WSACleanup吗?我们有几个应用程序可以在代码中的不同点终止,因此我们希望避免在代码中将WSACleanup放在任何地方.我们可以通过DllMain调用WSAStartup/WSACleanup,因为我们有一个所有这些应用程序都使用的dll.但是,Microsoft严格建议不要通过DllMain使用WSAStartup/WSACleanup,因为这会导致死锁.我们可以将WSAStarup移出DllMain,并在访问Windows套接字库之前在所有应用程序的代码中的某一点调用它.而且,只要我们调用WSAStartup,我们就想使用atExit函数来注册对WSACleanup的调用.有没有人有这种方法的经验?谢谢!
我在winsock的recv()循环中遇到了问题.我试图在iResult == 0时终止循环,但是,循环仅在套接字关闭时结束.它似乎挂在最后一个recv(),其中iResult等于0.那么有关如何有效终止循环的任何想法?我的最终目标(无论iResult是否= 0;或许我的方法是错误的)是在读取所有发送的信息时停止循环.这是循环.
do
{
iResult = recv(socket, recvbuf, BUFLEN-1, 0);
if(iResult > 0){
// Null byte :)
// Remove that garbage >:(
recvbuf[iResult] = '\0';
printf("Recvbuf: %s\n\n\niResult: %d\n",recvbuf,iResult);
continue; // working properly
}
else if(iResult == 0)
// Connection closed properly
break;
else
{
printf("ERROR! %ld",WSAGetLastError());
break;
}
} while(iResult > 0);
Run Code Online (Sandbox Code Playgroud)
就像我说的,我收到的所有数据,我都无法退出循环.下一步是将数据写回服务器,但它会挂起,直到ping超时.套接字是SOCK_STREAM,BUFLEN定义为0x200
谢谢
我有一个linux应用程序,它通过UDP协议发送数据.它使用这些头文件:
#include <stdio.h>
/* standard C i/o facilities */
#include <stdlib.h>
/* needed for atoi() */
#include <unistd.h>
/* defines STDIN_FILENO, system calls,etc */
#include <sys/types.h> /* system data type definitions */
#include <sys/socket.h> /* socket specific definitions */
#include <netinet/in.h> /* INET constants and stuff */
#include <arpa/inet.h> /* IP address conversion stuff */
#include <netdb.h>
#include <string.h> /* for string and memset etc */
/* gethostbyname */
#include <iostream>
#include <fstream>
#include <opencv/highgui.h>
#include <opencv/cv.h>
#include <opencv/cxcore.h>
Run Code Online (Sandbox Code Playgroud)
我想制作我的应用程序的WIndows版本.但是上面的一些头文件在WIndows中不起作用,特别是那些UDP. …
最近,我们的整个QA环境从VMWare迁移到Hyper-V虚拟机.
我们的一个应用程序以每秒20K数据包的速率将UDP数据包发送到多播云.
虽然这在VMWare环境中运行良好,但Hyper-V使应用程序在几分钟的工作后抛出以下异常:
System.Net.Sockets.SocketException (0x80004005): An invalid argument was supplied
at System.Net.Sockets.Socket.Send(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
Run Code Online (Sandbox Code Playgroud)
在将套接字的发送缓冲区大小定义为1,000,000字节时,我还设法立即模仿了这个问题.
我该如何解决这个问题?
更新1:一旦发生异常,这是来自事件查看器的日志条目:
Faulting application name: Agent.exe, version: 1.0.12.7366, time stamp: 0x51389f69
Faulting module name: KERNELBASE.dll, version: 6.1.7601.18015, time stamp: 0x50b83c8a
Exception code: 0xe0434352
Fault offset: 0x0000c41f
Faulting process id: 0xaf0
Faulting application start time: 0x01ce1b4ce509dc7a
Faulting application path: C:\Users\DevUser\Desktop\QA\Agent.exe
Faulting module path: C:\Windows\syswow64\KERNELBASE.dll
Report Id: d2b45dce-8740-11e2-86f9-00155d022804
Run Code Online (Sandbox Code Playgroud)
更新2:UDP数据包的大小为100-200字节.
更新3:这是有问题的代码:
m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
m_socket.Ttl = 1; …Run Code Online (Sandbox Code Playgroud) connect()如果我使用自动分配的临时端口(5000-65534)范围内的端口连接到localhost,我可以可靠地获得一个Winsock套接字.具体来说,Windows似乎有一个系统范围的滚动端口号,它将尝试将其指定为客户端套接字的本地端口号.如果我创建套接字直到分配的数字刚好低于我的目标端口号,然后重复创建套接字并尝试连接到该端口号,我通常可以让套接字连接到自己.
我首先在一个重复尝试连接到localhost上的某个端口的应用程序中发生这种情况,当服务没有监听时,它很少成功建立连接并接收它最初发送的消息(恰好是Redis PING命令).
一个例子,在Python中(无需监听目标端口即可运行):
import socket
TARGET_PORT = 49400
def mksocket():
return socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
while True:
sock = mksocket()
sock.bind(('127.0.0.1', 0))
host, port = sock.getsockname()
if port > TARGET_PORT - 10 and port < TARGET_PORT:
break
print port
while port < TARGET_PORT:
sock = mksocket()
err = None
try:
sock.connect(('127.0.0.1', TARGET_PORT))
except socket.error, e:
err = e
host, port = sock.getsockname()
if err:
print 'Unable to connect to port %d, used local port %d: %s' % (TARGET_PORT, …Run Code Online (Sandbox Code Playgroud)