8 个解决方案
#1
建立连接后标志用户的IP地址对以后进行判断,线程之间的通讯,消息通知事件!
#2
所有的用户都跟服务器连接,服务器通过IP地址知道要转发的用户,也就是那一个线程,然后转发数据,希望各位大虾能给点代码参考,非常感谢!!!
#3
其实不需要每个用户都一个线程,实际上只需要2个线程就可以实现多用户连接.定义一个Socket数组存放所有用户连接。服务器接受消息时可以知道客户的Socket序号,然后根据Socket调用Socket的API函数得到IP地址就可以,有了IP地址就可以再调用API函数找到对于的Socket,再发送消息就可以了。
#4
谢谢上面的仁兄! 您说的:"有了IP地址就可以再调用API函数找到对于的Socket",这个功能实现的代码该怎么写?万分感谢!!!
如果按照我的做法即:“当客户端访问 服务器时候,服务器为每个用户分别开一个线程”,知道IP,怎么可以知道它对应的与服务器建立连接的线程,实现代码应该怎么写,谢谢!!!!
如果按照我的做法即:“当客户端访问 服务器时候,服务器为每个用户分别开一个线程”,知道IP,怎么可以知道它对应的与服务器建立连接的线程,实现代码应该怎么写,谢谢!!!!
#5
自己顶一下!!
#6
建一个数组或链表来保存每个连接的信息结构
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,看你的情况了.
{
消息判断及相应的处理;
}
}
}
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,看你的情况了.
{
消息判断及相应的处理;
}
}
}
#7
#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就是.
#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就是.
#8
UP
#1
建立连接后标志用户的IP地址对以后进行判断,线程之间的通讯,消息通知事件!
#2
所有的用户都跟服务器连接,服务器通过IP地址知道要转发的用户,也就是那一个线程,然后转发数据,希望各位大虾能给点代码参考,非常感谢!!!
#3
其实不需要每个用户都一个线程,实际上只需要2个线程就可以实现多用户连接.定义一个Socket数组存放所有用户连接。服务器接受消息时可以知道客户的Socket序号,然后根据Socket调用Socket的API函数得到IP地址就可以,有了IP地址就可以再调用API函数找到对于的Socket,再发送消息就可以了。
#4
谢谢上面的仁兄! 您说的:"有了IP地址就可以再调用API函数找到对于的Socket",这个功能实现的代码该怎么写?万分感谢!!!
如果按照我的做法即:“当客户端访问 服务器时候,服务器为每个用户分别开一个线程”,知道IP,怎么可以知道它对应的与服务器建立连接的线程,实现代码应该怎么写,谢谢!!!!
如果按照我的做法即:“当客户端访问 服务器时候,服务器为每个用户分别开一个线程”,知道IP,怎么可以知道它对应的与服务器建立连接的线程,实现代码应该怎么写,谢谢!!!!
#5
自己顶一下!!
#6
建一个数组或链表来保存每个连接的信息结构
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,看你的情况了.
{
消息判断及相应的处理;
}
}
}
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,看你的情况了.
{
消息判断及相应的处理;
}
}
}
#7
#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就是.
#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就是.
#8
UP