mailslot和namedpipe有一点不好,它们是网络接口,容易被dos。
如果能使用USER32的话,可以各建立一个窗口,然后用WM_COPYDATA。
如果不能使用USER32,可以用命名事件和共享内存,不过要麻烦一些。
如果能使用USER32的话,可以各建立一个窗口,然后用WM_COPYDATA。
如果不能使用USER32,可以用命名事件和共享内存,不过要麻烦一些。
Windows中有两种基于虚拟文件系统的进程间通信方式——邮件槽和管道。邮件槽的优点是简单稳定,不会动不动就管道损坏,缺点是一次传输数据不能超过64kB,而且是单工模式,只能客户端发给服务器。不过我们可以手工实现有连接的双工通信。
客户端一般采用无限长等待方式,而服务端一般采用无等待循环检查的方式实现。
项目属性里的字符集设置为[使用多字节字符集]。
客户端:
#include <stdio.h>
#include <windows.h>
char appname[] = "myapp1";
int main()
{
char namebuf[1024] = "";
wsprintf(namebuf, "//./mailslot/%s/listen", appname);
HANDLE hlisten;
while (INVALID_HANDLE_VALUE == (hlisten = CreateFile(namebuf, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL)))
{
}
DWORD threadid = GetCurrentThreadId();
DWORD writenum = 0;
DWORD readnum = 0;
int clientid = -1;
DWORD sentnum = 0;
wsprintf(namebuf, "//./mailslot/%s/%u/client", appname, threadid);
HANDLE hclient = CreateMailslot(namebuf, 0, MAILSLOT_WAIT_FOREVER, NULL);
WriteFile(hlisten, &threadid, sizeof threadid, &writenum, NULL);
ReadFile(hclient, &clientid, sizeof clientid, &readnum, NULL);
CloseHandle(hlisten);
printf("connect established, connection id %d\n", clientid);
wsprintf(namebuf, "//./mailslot/%s/%u/server", appname, threadid);
HANDLE hserver = CreateFile(namebuf, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
WriteFile(hserver, "来自邮件槽客户端的问候", 22, &writenum, NULL);
ReadFile(hclient, &sentnum, sizeof sentnum, &readnum, NULL);
printf("sent %u bytes\n", sentnum);
WriteFile(hserver, "\033disconnect", 11, &writenum, NULL);
ReadFile(hclient, &sentnum, sizeof sentnum, &readnum, NULL);
printf("sent %u bytes\n", sentnum);
}
</windows.h></stdio.h>
服务端:
#include <stdio.h>
#include <windows.h>
char appname[] = "myapp1";
HANDLE listen_handle;
#define CONNECTION_NUM 16
HANDLE client_handle[CONNECTION_NUM];
HANDLE server_handle[CONNECTION_NUM];
int main()
{
char namebuf[1024] = "";
wsprintf(namebuf, "//./mailslot/%s/listen", appname);
listen_handle = CreateMailslot(namebuf, 0, 0, NULL);
if (listen_handle == INVALID_HANDLE_VALUE)
{
printf("ERR - cannot listen on %s\n", namebuf);
return 1;
}
printf("SUC - listen on %s\n", namebuf);
for (int i = 0; i < CONNECTION_NUM; i++)
{
client_handle[i] = INVALID_HANDLE_VALUE;
server_handle[i] = INVALID_HANDLE_VALUE;
}
DWORD threadid = 0;
DWORD readnum = 0;
DWORD writenum = 0;
while (true)
{
for (int i = 0; i < CONNECTION_NUM; i++)
{
if (client_handle[i] == INVALID_HANDLE_VALUE || server_handle == INVALID_HANDLE_VALUE)
{
CloseHandle(client_handle[i]);
CloseHandle(server_handle[i]);
client_handle[i] = INVALID_HANDLE_VALUE;
server_handle[i] = INVALID_HANDLE_VALUE;
ReadFile(listen_handle, &threadid, sizeof threadid, &readnum, NULL);
if (readnum < sizeof threadid)
continue;
wsprintf(namebuf, "//./mailslot/%s/%u/client", appname, threadid);
client_handle[i] = CreateFile(namebuf, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (client_handle[i] == INVALID_HANDLE_VALUE)
{
printf("ERR - connection %d cannot open %s\n", i, namebuf);
continue;
}
SetMailslotInfo(client_handle[i], 0);
printf("SUC - connection %d open %s\n", i, namebuf);
wsprintf(namebuf, "//./mailslot/%s/%d/server", appname, threadid);
server_handle[i] = CreateMailslot(namebuf, 0, 0, NULL);
if (server_handle[i] == INVALID_HANDLE_VALUE)
{
printf("ERR - connection %d cannot create %s\n", i, namebuf);
CloseHandle(client_handle[i]);
client_handle[i] = INVALID_HANDLE_VALUE;
continue;
}
printf("SUC - connection %d create %s\n", i, namebuf);
WriteFile(client_handle[i], &i, sizeof i, &writenum, NULL);
}
else
{
char buf[65537] = "";
char msgbuf[1024] = "";
ReadFile(server_handle[i], buf, 65536, &readnum, NULL);
if (readnum == 0)
continue;
printf("SUC - connection %d read %u bytes: %s\n", i, readnum, buf);
WriteFile(client_handle[i], &readnum, sizeof readnum, &writenum, NULL);
if (lstrcmpi(buf, "\033disconnect") == 0)
{
CloseHandle(client_handle[i]);
CloseHandle(server_handle[i]);
client_handle[i] = INVALID_HANDLE_VALUE;
server_handle[i] = INVALID_HANDLE_VALUE;
printf("SUC - connection %d closed\n", i);
continue;
}
}
}
}
}
</windows.h></stdio.h>