网络数据转发问题 谢谢!!! 当客户端访问 服务器时候,服务器为每个用户分别开一个线程 并且创建Socket用于传递数据。当某个用户把数据传输给服务器时,服务器又要把接收到的数据转发给另一个用户,从接收的数据中可以知道要转发的用户的IP地址,请问转发应该怎么实现?谢谢!! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 其实不需要每个用户都一个线程,实际上只需要2个线程就可以实现多用户连接.定义一个Socket数组存放所有用户连接。服务器接受消息时可以知道客户的Socket序号,然后根据Socket调用Socket的API函数得到IP地址就可以,有了IP地址就可以再调用API函数找到对于的Socket,再发送消息就可以了。 谢谢上面的仁兄! 您说的:"有了IP地址就可以再调用API函数找到对于的Socket",这个功能实现的代码该怎么写?万分感谢!!!如果按照我的做法即:“当客户端访问 服务器时候,服务器为每个用户分别开一个线程”,知道IP,怎么可以知道它对应的与服务器建立连接的线程,实现代码应该怎么写,谢谢!!!! 建一个数组或链表来保存每个连接的信息结构typedef struct _ConnInfo{ HANDLE hThread; SOCKET Socket; ULONG IP;}*P_ConnInfo;这样知道IP后在可以在数组或链中查询对应的套接字或线程句柄,然后使用该套接发送数据.如果一定要转到相应的线程发送数据,可以在为每个连接建立的线程中设置一个消息循环,在查找到上述连接信息后向该线程发送消息.Buf已知;IP已知;P_ConnInfo pConnInfo=List.Find(IP);//这个可以使用STL的list类或MFC的CList类,或数组if(pConnInfo)PostThreadMessage(pConnInfo->hThread,自定议消息,0,(LONG)Buf);线程消息循环的建立:void ThreadProc(void* pVoid){ MSG msg; while(GetMessage(&msg,0,0,0)) { switch(msg.lParam)//或if,看你的情况了. { 消息判断及相应的处理; } } } #include <winsock2.h>#include <stdio.h>#define PORT 5150#define MSGSIZE 1024#pragma comment(lib, "ws2_32.lib")int g_iTotalConn = 0;SOCKET g_CliSocketArr[MAXIMUM_WAIT_OBJECTS];WSAEVENT g_CliEventArr[MAXIMUM_WAIT_OBJECTS];DWORD WINAPI WorkerThread(LPVOID);void Cleanup(int index);int main(){ WSADATA wsaData; SOCKET sListen, sClient; SOCKADDR_IN local, client; DWORD dwThreadId; int iaddrSize = sizeof(SOCKADDR_IN); // Initialize Windows Socket library WSAStartup(0x0202, &wsaData); // Create listening socket sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Bind local.sin_addr.S_un.S_addr = htonl(INADDR_ANY); local.sin_family = AF_INET; local.sin_port = htons(PORT); bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN)); // Listen listen(sListen, 3); // Create worker thread CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId); while (TRUE) { // Accept a connection sClient = accept(sListen, (struct sockaddr *)&client, &iaddrSize); printf("Accepted client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); // Associate socket with network event g_CliSocketArr[g_iTotalConn] = sClient; g_CliEventArr[g_iTotalConn] = WSACreateEvent(); WSAEventSelect(g_CliSocketArr[g_iTotalConn], g_CliEventArr[g_iTotalConn], FD_READ | FD_CLOSE); g_iTotalConn++; }}DWORD WINAPI WorkerThread(LPVOID lpParam){ int ret, index; WSANETWORKEVENTS NetworkEvents; char szMessage[MSGSIZE]; while (TRUE) { ret = WSAWaitForMultipleEvents(g_iTotalConn, g_CliEventArr, FALSE, 1000, FALSE); if (ret == WSA_WAIT_FAILED || ret == WSA_WAIT_TIMEOUT) { continue; } index = ret - WSA_WAIT_EVENT_0; WSAEnumNetworkEvents(g_CliSocketArr[index], g_CliEventArr[index], &NetworkEvents); if (NetworkEvents.lNetworkEvents & FD_READ) { // Receive message from client ret = recv(g_CliSocketArr[index], szMessage, MSGSIZE, 0); if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)) { Cleanup(index); } else { szMessage[ret] = '\0'; send(g_CliSocketArr[index], szMessage, strlen(szMessage), 0); } } if (NetworkEvents.lNetworkEvents & FD_CLOSE) { Cleanup(index); } } return 0;}void Cleanup(int index){ closesocket(g_CliSocketArr[index]); WSACloseEvent(g_CliEventArr[index]); if (index < g_iTotalConn - 1) { g_CliSocketArr[index] = g_CliSocketArr[g_iTotalConn - 1]; g_CliEventArr[index] = g_CliEventArr[g_iTotalConn - 1]; } g_iTotalConn--;}以上代码节选自书籍上的代码。你的问题只要略为修改就可以达到目的。至于由sock得到ip地址可以用int getpeername(SOCKET s, struct sockaddr FAR * name, int FAR * namelen )函数。遍历sock数组调用此函数,若得到的ip于你的转发ip相等,必定是此sock了,然后send就是. 对整个文件映射问题!!!! 如何修改clistCtrl的header高度及使得文字换行 关于调试器的设置 vc 与rs232 通信的端口设置win98行 xp和2k 不行? 如何得到一个线程类自己的HWND WinRaR 3.0 以上的版本的压缩文件有没有得到密码的方法! 怎么样锁定和解锁鼠标?? 请问高手! 我用的SDI我想利用CTree,实现类似资源管理器的功能,如何实现。我是小白,贴代码看不懂。希望有详细的实现过程。希望大家帮忙。 链接错误,郁闷中 句柄HWND 的问题 未知错误
typedef struct _ConnInfo
{
HANDLE hThread;
SOCKET Socket;
ULONG IP;
}*P_ConnInfo;
这样知道IP后在可以在数组或链中查询对应的套接字或线程句柄,然后使用该套接发送数据.如果一定要转到相应的线程发送数据,可以在为每个连接建立的线程中设置一个消息循环,
在查找到上述连接信息后向该线程发送消息.Buf已知;
IP已知;
P_ConnInfo pConnInfo=List.Find(IP);//这个可以使用STL的list类或MFC的CList类,或数组
if(pConnInfo)
PostThreadMessage(pConnInfo->hThread,自定议消息,0,(LONG)Buf);线程消息循环的建立:
void ThreadProc(void* pVoid)
{
MSG msg;
while(GetMessage(&msg,0,0,0))
{
switch(msg.lParam)//或if,看你的情况了.
{
消息判断及相应的处理;
}
}
}
#include <stdio.h>#define PORT 5150
#define MSGSIZE 1024#pragma comment(lib, "ws2_32.lib")int g_iTotalConn = 0;
SOCKET g_CliSocketArr[MAXIMUM_WAIT_OBJECTS];
WSAEVENT g_CliEventArr[MAXIMUM_WAIT_OBJECTS];DWORD WINAPI WorkerThread(LPVOID);
void Cleanup(int index);int main()
{
WSADATA wsaData;
SOCKET sListen, sClient;
SOCKADDR_IN local, client;
DWORD dwThreadId;
int iaddrSize = sizeof(SOCKADDR_IN); // Initialize Windows Socket library
WSAStartup(0x0202, &wsaData); // Create listening socket
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Bind
local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
local.sin_family = AF_INET;
local.sin_port = htons(PORT);
bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN)); // Listen
listen(sListen, 3); // Create worker thread
CreateThread(NULL, 0, WorkerThread, NULL, 0, &dwThreadId); while (TRUE)
{
// Accept a connection
sClient = accept(sListen, (struct sockaddr *)&client, &iaddrSize);
printf("Accepted client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); // Associate socket with network event
g_CliSocketArr[g_iTotalConn] = sClient;
g_CliEventArr[g_iTotalConn] = WSACreateEvent();
WSAEventSelect(g_CliSocketArr[g_iTotalConn],
g_CliEventArr[g_iTotalConn],
FD_READ | FD_CLOSE);
g_iTotalConn++;
}
}DWORD WINAPI WorkerThread(LPVOID lpParam)
{
int ret, index;
WSANETWORKEVENTS NetworkEvents;
char szMessage[MSGSIZE]; while (TRUE)
{
ret = WSAWaitForMultipleEvents(g_iTotalConn, g_CliEventArr, FALSE, 1000, FALSE);
if (ret == WSA_WAIT_FAILED || ret == WSA_WAIT_TIMEOUT)
{
continue;
} index = ret - WSA_WAIT_EVENT_0;
WSAEnumNetworkEvents(g_CliSocketArr[index], g_CliEventArr[index], &NetworkEvents); if (NetworkEvents.lNetworkEvents & FD_READ)
{
// Receive message from client
ret = recv(g_CliSocketArr[index], szMessage, MSGSIZE, 0);
if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))
{
Cleanup(index);
}
else
{
szMessage[ret] = '\0';
send(g_CliSocketArr[index], szMessage, strlen(szMessage), 0);
}
} if (NetworkEvents.lNetworkEvents & FD_CLOSE)
{
Cleanup(index);
}
}
return 0;
}void Cleanup(int index)
{
closesocket(g_CliSocketArr[index]);
WSACloseEvent(g_CliEventArr[index]); if (index < g_iTotalConn - 1)
{
g_CliSocketArr[index] = g_CliSocketArr[g_iTotalConn - 1];
g_CliEventArr[index] = g_CliEventArr[g_iTotalConn - 1];
}
g_iTotalConn--;
}
以上代码节选自书籍上的代码。你的问题只要略为修改就可以达到目的。至于由sock得到ip地址可以用int getpeername(SOCKET s, struct sockaddr FAR * name, int FAR * namelen )函数。遍历sock数组调用此函数,若得到的ip于你的转发ip相等,必定是此sock了,然后send就是.