基于select模式的 一个工作线程主线程在接受客户端的连接,工作线程在处理数据能否在以下代码基础上实现一个功能:有客户端连接后,就接受数据,然后 写到磁盘中,注:保存磁盘有讲究, 文件名必须是1001,1002,1003,以此类推。 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));
// Add socket to g_CliSocketArr
g_CliSocketArr[g_iTotalConn++] = sClient;
}
DWORD WINAPI WorkerThread(LPVOID lpParam)
{
int i;
fd_set fdread;
int ret;
struct timeval tv = {1, 0};
char szMessage[MSGSIZE];
while (TRUE)
{
FD_ZERO(&fdread);
for (i = 0; i < g_iTotalConn; i++)
{
FD_SET(g_CliSocketArr[i], &fdread);
} // We only care read event
ret = select(0, &fdread, NULL, NULL, &tv);
if (ret == 0)
{ // Time expired
continue;
}
for (i = 0; i < g_iTotalConn; i++)
{
if (FD_ISSET(g_CliSocketArr, &fdread))
{ // A read event happened on g_CliSocketArr
ret = recv(g_CliSocketArr, szMessage, MSGSIZE, 0);
if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))
{
// Client socket closed
printf("Client socket %d closed.\n", g_CliSocketArr);
closesocket(g_CliSocketArr);
if (i < g_iTotalConn - 1)
{
g_CliSocketArr[i--] = g_CliSocketArr[--g_iTotalConn];
}
}
else
{
// We received a message from client
szMessage[ret] = '\0';
send(g_CliSocketArr[i], szMessage, strlen(szMessage), 0);
}
} //if
}//for
}//while
return 0;
}
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));
// Add socket to g_CliSocketArr
g_CliSocketArr[g_iTotalConn++] = sClient;
}
DWORD WINAPI WorkerThread(LPVOID lpParam)
{
int i;
fd_set fdread;
int ret;
struct timeval tv = {1, 0};
char szMessage[MSGSIZE];
while (TRUE)
{
FD_ZERO(&fdread);
for (i = 0; i < g_iTotalConn; i++)
{
FD_SET(g_CliSocketArr[i], &fdread);
} // We only care read event
ret = select(0, &fdread, NULL, NULL, &tv);
if (ret == 0)
{ // Time expired
continue;
}
for (i = 0; i < g_iTotalConn; i++)
{
if (FD_ISSET(g_CliSocketArr, &fdread))
{ // A read event happened on g_CliSocketArr
ret = recv(g_CliSocketArr, szMessage, MSGSIZE, 0);
if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))
{
// Client socket closed
printf("Client socket %d closed.\n", g_CliSocketArr);
closesocket(g_CliSocketArr);
if (i < g_iTotalConn - 1)
{
g_CliSocketArr[i--] = g_CliSocketArr[--g_iTotalConn];
}
}
else
{
// We received a message from client
szMessage[ret] = '\0';
send(g_CliSocketArr[i], szMessage, strlen(szMessage), 0);
}
} //if
}//for
}//while
return 0;
}
解决方案 »
- vc2008中MSComm控件的使用问题
- console程序关闭事件
- 请问下面程序中的 student(int i=10):n(i){}; 是什么意思,其中的:(冒号)表示什么,怎么用?
- 请教用POP3协议 在VC环境下如何编写接收带附件的邮件程序
- 请问四个关于atl和idl的题目,请高手指点
- 求助
- 请问数据文件存储需要20TB的容量,请问使用什么硬件和怎样编程写入数据。
- 怎样改变标题栏大小?
- 请问怎样才能在列表视图控件(ListCtrl)中查找数据,我用的是报表模式(REPORT),在线等待,回答有分
- 套接字 接收 服务器程序 自动关闭
- WindowsAPI很多都不会用怎么办
- ActiveX网格控件(DataGrid)
using namespace std;DWORD WINAPI WorkerThread(LPVOID lpParam)
{
...
else
{
// We received a message from client ofstream filestream;
char name[4];
sprintf(name, "%d", i);
filestream.open("name", ios::out|ios::app);
filestream.write(szMessage, ret);
filestream.close(); szMessage[ret] = '\0';
send(g_CliSocketArr[i], szMessage, strlen(szMessage), 0);
}
...
}
如果是一个连接对应一个文件的话,我想这样就可以简单实现了。
其他地方都省略了,你如果想改变文件名的基数就在sprintf那里动一下手脚就行了。
但是一旦有个socket先下线了,那么 10个必然变成9个了。 顺序就混乱了。 for (i = 0; i < g_iTotalConn; i++)
{
if (FD_ISSET(g_CliSocketArr, &fdread))
{ // A read event happened on g_CliSocketArr
ret = recv(g_CliSocketArr, szMessage, MSGSIZE, 0);
if (ret == 0 || (ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET))
{
// Client socket closed
printf("Client socket %d closed.\n", g_CliSocketArr);
closesocket(g_CliSocketArr);
if (i < g_iTotalConn - 1)
{
g_CliSocketArr[i--] = g_CliSocketArr[--g_iTotalConn];
}
}
else
{
// We received a message from client //保存到磁盘里
szMessage[ret] = '\0';
send(g_CliSocketArr[i], szMessage, strlen(szMessage), 0);
}
} //if
}//for
要想一个socket对应一个文件,我想有两个简单的方法可以解决
1.定义一个结构
struct CLIENT{
SOCKET sock;
char filename[4];
};然后你数组里就不要存socket了直接存这个结构,
socket与文件一一对应。
2.可以使用map
map<SCOKET, char*>
同时建立一个保存文件名的数组,用map建立socket和文件名的关联。我认为第一个相对来讲好一点,因为如果以后你需要针对每个连接处理更多问题的时候可能需要添加更多的参数一类的内容。
当然你把struct改成class是一样的。
多谢你了啊,呵呵这代码是来自网上,我只是想修改一下代码中有个bug, 如是最后一个套接字出错,竟然没有处理。不知道是我多想,还是 我猜错了