在嵌入式系统开发中,网络通信是一个重要的组成部分。本文将介绍如何在嵌入式Visual C++3.0环境下进行网络编程,包括初始化Winsock、创建服务器端和客户端套接字、同步线程的创建与使用,以及如何关闭套接字。
在开始网络编程之前,需要初始化Winsock组件。这可以通过调用WSAStartup API来实现。以下是初始化Winsock的示例代码:
WSADATA wsaData;
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
MessageBox(hWnd, TEXT("Fail to initialize the Winsock DLL!"), TEXT("MySocket"), MB_OK | MB_ICONEXCLAMATION);
return 1;
} else {
return 0;
}
这段代码首先定义了一个WSADATA类型的变量wsaData,然后调用WSAStartup函数初始化Winsock DLL。如果初始化失败,会弹出一个消息框提示用户。
在初始化Winsock之后,需要创建一个服务器端套接字来监听客户端的连接请求。以下是创建服务器端套接字的示例代码:
memset(&sckAddress, 0, sizeof(sockaddr_in));
sckClient = socket(AF_INET, SOCK_STREAM, 0);
sckAddress.sin_port = htons(atoi(port));
sckAddress.sin_family = AF_INET;
sckAddress.sin_addr.s_addr = inet_addr(host);
if (connect(sckClient, (struct sockaddr *)&sckAddress, sizeof(sckAddress)) != SOCKET_ERROR) {
hThread2 = CreateThread(NULL, 0, ReadInBuffer, hWnd, 0, &dwThreadID);
} else {
MessageBox(hWnd, TEXT("Client~Fail to establish the connection!"), TEXT("MySocket"), MB_OK | MB_ICONEXCLAMATION);
}
这段代码首先重置了sockaddr_in结构体,然后创建了一个套接字。接着,它设置了服务器的端口号、协议族和IP地址。如果连接成功,它会创建一个读取输入缓冲区的同步线程。否则,会弹出一个消息框提示用户连接失败。
在服务器端套接字创建之后,需要创建一个同步线程来监听客户端的连接请求。以下是监听线程的示例代码:
DWORD WINAPI StartListen(LPVOID pParam) {
if (sckServer != INVALID_SOCKET) {
sckAddress.sin_port = htons(atoi(port));
sckAddress.sin_family = AF_INET;
sckAddress.sin_addr.s_addr = INADDR_ANY;
bind(sckServer, (struct sockaddr *)&sckAddress, sizeof(sckAddress));
listen(sckServer, 1);
do {
fds = 0;
tv.tv_sec = 1;
tv.tv_usec = 1;
FD_ZERO(&fds);
FD_SET(sckServer, &fds);
if (select(0, &fds, NULL, NULL, &tv) == 0) continue;
if (FD_ISSET(sckServer, &fds)) {
sckClient = accept(sckServer, NULL, 0);
closesocket(sckServer);
sckServer = INVALID_SOCKET;
SetDlgItemText(hWnd, IDC_STATUS1, TEXT("Connected"));
hThread2 = CreateThread(NULL, 0, ReadInBuffer, hWnd, 0, &dwThreadID);
break;
}
} while (sckServer != INVALID_SOCKET);
} else {
MessageBox(hWnd, TEXT("Server~Fail to open the socket!"), TEXT("MySocket"), MB_OK | MB_ICONEXCLAMATION);
}
}
这段代码首先检查服务器端套接字是否有效。如果有效,它会设置端口号、协议族和IP地址,然后绑定套接字并监听端口。接着,它进入一个无限循环,不断检查套接字状态,直到收到一个有效的连接请求。如果收到请求,它会接受连接,关闭监听套接字,更新状态控件,并创建一个新的读取输入缓冲区的同步线程。
在服务器端套接字创建之后,需要创建一个同步线程来读取客户端发送的数据。以下是读取输入缓冲区的示例代码:
HWND hWnd = NULL;
char *Buff = NULL;
TCHAR *wBuff = NULL;
int err;
hWnd = (HWND)pParam;
wBuff = new TCHAR[1024];
Buff = new char[1024];
if (sckClient != INVALID_SOCKET) {
while (true) {
memset(wBuff, TEXT('\0'), 1024 * sizeof(TCHAR));
memset(Buff, '\0', 1024);
err = recv(sckClient, Buff, 1024, 0);
if (err == SOCKET_ERROR || err <= 0) {
CloseSocket(hWnd);
break;
} else {
mbstowcs(wBuff, Buff, 1024);
SetDlgItemText(hWnd, IDC_EDIT3, wBuff);
}
}
}
delete Buff;
ExitThread(WM_QUIT);
return 0;
这段代码首先定义了一些变量,包括窗口句柄、字符缓冲区和宽字符缓冲区。然后,它进入一个无限循环,不断读取客户端发送的数据。如果读取失败或没有数据,它会关闭套接字并退出线程。否则,它会将接收到的数据从多字节字符集转换为Unicode字符集,并显示在编辑框中。
在不再需要套接字或检测到客户端连接丢失时,需要关闭套接字。以下是关闭套接字的示例代码:
if (sckServer != INVALID_SOCKET) {
if (closesocket(sckServer) == 0) {
sckServer = INVALID_SOCKET;
} else {
MessageBox(hWnd, TEXT("Server~Fail to close the socket."), TEXT("MySocket"), MB_OK | MB_ICONEXCLAMATION);
}
}
这段代码首先检查服务器端套接字是否有效。如果有效,它会关闭套接字并重置服务器端套接字变量。如果关闭失败,它会弹出一个消息框提示用户。