使用WinSocket客户端/服务器应用程序重复使用插座
reusing sockets with WinSocket client/server application
我有2个简单的应用程序,一个客户端和一台服务器。客户端连接到服务器,服务器将数据发送给客户端。在客户端应用程序的主要循环中,我每次要收到另一个信息时都关闭插座并创建一个新的套接字。它有效,但对我来说看起来不正确。这是正确的吗?我是否真的需要每次关闭并重新打开插座,还是有其他方法可以这样做?
客户端:
int main(){
DWORD id;
SOCKET s;
struct sockaddr_in sa;
WSADATA wsas;
WORD wersja;
int recv_size;
LPTHREAD_START_ROUTINE WINAPI funkcja = getCommend;
watek = CreateThread(NULL, 0, funkcja, 0, 0, &id);
wersja = MAKEWORD(2, 0);
WSAStartup(wersja, &wsas);
memset((void *)(&sa), 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(PORT);
sa.sin_addr.s_addr = inet_addr("25.62.229.110");
int result;
s = socket(AF_INET, SOCK_STREAM, 0);
result = connect(s, (struct sockaddr FAR *) &sa, sizeof(sa));
if (result == SOCKET_ERROR)
{
printf("nBłąd połączenia!");
return 1;
}
int a;
if ((recv_size = recv(s, server_reply, SIZE, 0)) == SOCKET_ERROR)
{
printf("recv failedn");
}
else{
while (result != SOCKET_ERROR){
//printf("%sn", server_reply);
closesocket(s);
Sleep(1000);
s = socket(AF_INET, SOCK_STREAM, 0);
result = connect(s, (struct sockaddr FAR *) &sa, sizeof(sa));
if (result == SOCKET_ERROR){
break;
}
result = recv_size = recv(s, server_reply, SIZE, 0);
}
}
getchar();
closesocket(s);
TerminateThread(watek, NULL);
WSACleanup();
return 1;
}
服务器:
int main(){
DWORD id;
SOCKET s, new_socket;
LPTHREAD_START_ROUTINE WINAPI funkcja = getCommend;
struct sockaddr_in sa, sc;
WSADATA wsas;
int c;
watek = CreateThread(NULL,0,funkcja,0,0,&id);
WSAStartup(MAKEWORD(1, 1), &wsas);
s = socket(AF_INET, SOCK_STREAM, 0);
//memset((void *)(&sa), 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(PORT);
sa.sin_addr.s_addr = htonl(INADDR_ANY);
bind(s, (struct sockaddr FAR*)&sa, sizeof(sa));
listen(s, 5);
puts("Czekam na polaczenie...");
c = sizeof(struct sockaddr_in);
while ((new_socket = accept(s, (struct sockaddr *)&sc, &c)) != INVALID_SOCKET)
{
//puts("polaczenie zaakceptowane");
send(new_socket, message, strlen(message), 0);
}
if (new_socket == INVALID_SOCKET)
{
printf("Nie udane połaczenie, blad nr : %d", WSAGetLastError());
return 1;
}
TerminateThread(watek, NULL);
getchar();
}
好吧,这里的某些事情不是很常见。
首先,您通常用英语命名变量,而不是用拉丁字母编写的其他语言。我可能会为此感到沮丧,但这是出于某种原因的常见做法。
第二,我会在OS特定API上使用C 标准。为什么不使用std::thread
而不是Winapi线程?它更简单,简短和优雅。
第三,您的代码为100%程序。您没有标准的C 套接字类,但这并不意味着您不能(或不应该)编写自己的插座类,该类以优雅的方式处理,绑定,发送和接收功能。
第四,即使MSDN示例如此,s
也不是变量的好名称。acceptingSocket
可能是。
关于您的实际问题:您在这里有很多选择,我能想到的3个:
1)不要关闭套接字,并继续在循环内接收数据。
优点:易于编写。当服务器拥有新数据时,客户端立即将其获取。缺点:当您的服务器每次具有更多连接时,这不是一个好方法,因为它将崩溃。
2)让服务器打包数据。然后,客户以预定义的间隔打开连接,请立即询问所有累积数据并接收它。
优点:CPU资源中节省的三个资源最多选项。缺点:您的客户不会立即获取数据,而是以预定义的间隔
3)让客户在每个会话的开始中将本地IP和端口发送到服务器。然后,让客户端在本地主机上保持一个有界的套接字,等待连接。每当服务器有新的东西告诉客户端时 - 它只需使用已保存的IP和端口连接到客户端,发送数据并关闭连接即可。然后,客户返回以等待新连接。这种方式
优点:在这种情况下,服务器每次都会有尽可能少的连接,如果您将服务器打算到服务器许多客户端,那么Wich是一件好事。缺点:重量实际上落在客户上,在许多情况下,这不是最好的事情。
通常的单连接方法是:
Create socket
bind socket
Listen on socket
newsocket = accept on socket
while no accept errors
while newsocket connected and error free
process newsocket
newsocket = accept on socket
可以处理多种连接。
多线程:
create thread pool
Create socket
bind socket
Listen on socket
while no errors
newsocket = accept on socket
hand newsocket off to thread pool for processing
一单读选择的基于
Create socket
bind socket
Listen on socket
add socket to readFD list
while no errors
select on readFD list
if socket selected
newsocket = accept on socket
add newsocket to readFD list
while other sockets selected
process other sockets
- 试图在visual studio上用C++创建一个桌面应用程序
- FFmpeg:制作一个应用程序比直接使用ffmepg更好吗
- 在C应用程序中运行C++(带有STL)函数
- 使用VerQueryValue检索应用程序的文件描述
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 使用调试/崩溃报告将应用程序部署到客户端
- C++控制台应用程序阻止退出
- 码头化的C++应用程序是否向后兼容早期的内核版本
- 将应用程序从32位移植到64位时出现问题
- 如何改变c++应用程序的视觉效果
- WM_CTLCOLORSTATIC从未在WIN32应用程序中触发
- PC中的程序和PHONE中的本机描述应用程序之间的数据连接
- 应用程序崩溃并显示"symbol _ZdlPvm, version Qt_5 not defined in file libQt5Core.so.5 with link time reference"
- 示例外壳应用程序显示的 V8 "segmentation fault (core dumped)"错误
- phytec phyBOARD iMX-6在从闪存而不是SD卡运行qt5 opengles应用程序时表现不佳(FPS减半
- 为什么导入Mixed native/CLR lib.dll的本机C++应用程序没有在Mixed lib.dll中的外部变
- 如何从Windows应用程序输出到标准?
- C++应用程序 MySQL odbc 数据库连接错误:在引发"otl_tmpl_exception<>"实例后终止调用
- 使用WinSocket客户端/服务器应用程序重复使用插座
- 服务器应用程序.始终打开的插座