Multithread in Socket programming
I'm building a downloader app that can download only through http protocol by using VC++6. I defined UNICODE macro to display vietnamese in UI and using Microsoft SDK 2003 to compile. But my app have problems. It downloads multithread, but when it seems to be done, it wait for a long time to finish download. I debugged it and detect that some thread is created by compiler, not by my app. But I don't know what is the function of these thread.
Anyone can help me?
Tks you very much.
My english is not good. So sorry for any inconvenience. :)
Here is my code.
Code:
#include "WinSock2.h"
#include "Ws2tcpip.h"
#pragma comment(lib,"ws2_32.lib")
#include <stdio.h>
#include <windows.h>
#include <commctrl.h>
#include "Resource.h"
#include <process.h>
#include <winnls.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <STRING.H>
#include <ASSERT.H>
#include "Richedit.h"
#define URL "http://www.cpuid.com/medias/files/softwares/cpu-z/cpu-z_1.57.1-setup-en.exe"
//#define URL "http://tracker.vcmedia.vn/HDPlayer/cpuz.exe"
#define URLJRE "http://admicro2.vcmedia.vn/adt/setup.exe"
#define DESTINATION "C:\\SilentInstaller.exe"
#define BUFFER_LENGTH 1024*32
#define WIN32_LEAN_AND_MEAN
#define MAX_THREAD 2 //The number of thread
#define GET_MESSAGE "GET %s HTTP/1.1\r\nHost: %s\r\nUser-Agent: %s\r\nRange: bytes=%lld-%11d\r\nConnection: close\r\n\r\n"
//---------------------------------------------------------------------------
// The main window class name.
static TCHAR szWindowClass[] = TEXT("Tr\xECnh \x63\xE0i \x111\x1EB7t");
// The string that appears in the application's title bar.
static TCHAR szTitle[] = TEXT("Tr\xECnh \x63\xE0i \x111\x1EB7t");
//the boolean to end the thread that change the lable's text
volatile bool running = true;
//host and server to download
volatile char* host = NULL;
volatile char* server = NULL;
volatile int content_length = 0;
int download_length = 0;
int k = 0;
struct addrinfo hints;
struct addrinfo* ai;
HFONT prog_font = CreateFont(17,0,0,0,FW_DONTCARE,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_MODERN,TEXT("Arial"));
//---------------------------------------------------------------------------
HWND hWnd, hWndPB, hWndLB;
HINSTANCE hInst;
CRITICAL_SECTION cs;
LRESULT APIENTRY MainProc(HWND, UINT, WPARAM, LPARAM);
unsigned __stdcall DownloadManager(void* );
unsigned __stdcall DownloadThread (void*);
int Init(HINSTANCE, HINSTANCE, LPSTR, int);
unsigned __stdcall SetLabel(void*);
//---------------------------------------------------------------------------
short get_client_port(struct sockaddr *clientInformation)
{
//carries the port number that client connected from
short portNumber = 1;
//check the family version of client IP address, so you
//can know where to cast, either to sockaddr_in or sockaddr_in6
//and then grab the port after casting
if (clientInformation->sa_family == AF_INET) {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)clientInformation;
portNumber = (short) ntohs(ipv4->sin_port);
return portNumber;
}else{
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)clientInformation;
portNumber = (short) ntohs(ipv6->sin6_port);
return portNumber;
}
}
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
hInst = hInstance;
HANDLE hDownloadThread;
hDownloadThread = (HANDLE) _beginthreadex( NULL, 0, &DownloadManager, NULL, 0, NULL);
Init(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
return FALSE;
}
//---------------------------------------------------------------------------
int Init(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = MainProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_ICON1));
hInst = hInstance; // Store instance handle in our global variable
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
TEXT("\x43h\x1B0\x1A1ng tr\xECnh \x63\xE0i \x111\x1EB7t \x62\x1ECB l\x1ED7i!"),
TEXT("Tr\xECnh \x63\xE0i \x111\x1EB7t"),
NULL);
return 1;
}
HWND hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU,
CW_USEDEFAULT, CW_USEDEFAULT,
585, 100,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL,
TEXT("\x43h\x1B0\x1A1ng tr\xECnh \x63\xE0i \x111\x1EB7t \x62\x1ECB l\x1ED7i!"),
TEXT("Tr\xECnh \x63\xE0i \x111\x1EB7t"),
NULL);
return 1;
}
// The parameters to ShowWindow explained:
// hWnd: the value returned from CreateWindow
// nCmdShow: the fourth parameter from WinMain
ShowWindow(hWnd,
nCmdShow);
UpdateWindow(hWnd);
// Main message loop:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
//---------------------------------------------------------------------------
LRESULT APIENTRY MainProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
static HBRUSH hbrBackground;
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
hWndPB = CreateWindowEx(0, PROGRESS_CLASS, NULL,
WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
12, 30, 550, 17,
hwnd, NULL, hInst, NULL);
hWndLB = CreateWindowEx(0, TEXT("Static"), NULL,WS_CHILD | WS_VISIBLE ,12,5,300,20,hwnd,NULL,hInst,NULL);
hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
SetWindowText(hWndLB, TEXT("\x110\x61ng t\x1EA3i H\x64pl\x61y\x65r"));
SendMessage(hWndPB, WM_SETFONT,(WPARAM)prog_font,0);
SendMessage(hWndLB, WM_SETFONT,(WPARAM)prog_font,0);
SendMessage(hWnd, WM_SETFONT,(WPARAM)prog_font,0);
return TRUE;
break;
case WM_CTLCOLORDLG:
return (LONG)hbrBackground;
case WM_CTLCOLORSTATIC:
{
HDC hdcStatic = (HDC)wParam;
SetBkMode(hdcStatic, TRANSPARENT);
return (LONG)hbrBackground;
}
default: return DefWindowProc(hwnd,msg,wParam,lParam);
}
return 0;
}
//---------------------------------------------------------------------------
void RunInstaller(){
HANDLE hLabelThread;
running = true;
hLabelThread = (HANDLE) _beginthreadex(NULL, 0, SetLabel, TEXT("\x110\x61ng \x63\xE0i \x111\x1EB7t H\x64pl\x61y\x65r"), 0, NULL);
TCHAR cmd[] = TEXT(DESTINATION);
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
// Start the child process.
if( !CreateProcess( NULL, // No module name (use command line)
cmd, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
MessageBox(hWnd, TEXT("Kh\xF4ng th\x1EC3 \x63\xE0i \x111\x1EB7t \x63h\x1B0\x1A1ng tr\xECnh H\x64pl\x61y\x65r!"),TEXT("L\x1ED7i"), MB_OK);
return;
}
// Wait until child process exits.`
WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
CloseHandle( hLabelThread);
}
//---------------------------------------------------------------------------
unsigned __stdcall DownloadManager(void* param){
// HANDLE hLabelThread;
HANDLE hDownloadThread[MAX_THREAD] = {NULL};
InitializeCriticalSection( &cs );
struct WSAData* wd = (struct WSAData*)malloc(sizeof(struct WSAData));
if (WSAStartup(MAKEWORD(2, 0), wd)){
MessageBox(hWnd, TEXT("Kh\xF4ng th\x1EC3 k\x1EBFt n\x1ED1i v\x1EDBi Int\x65rn\x65t!"), TEXT("L\x1ED7i"),MB_OK);
exit(1);
}
free(wd);
SOCKET sock;
FILE *f = NULL;
running = true;
// hLabelThread = (HANDLE)_beginthreadex(0, 0 , SetLabel, TEXT("\x110\x61ng t\x1EA3i H\x64pl\x61y\x65r") , 0, NULL);
//HKEY hKey;
/* if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\JavaSoft\\Java Runtime Environment"), 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS){
host = strdup(URL);
server = strdup(URL);
} else{
host = strdup(URL);
server = strdup(URL);
}*/
host = strdup(URL);
server = strdup(URL);
if (strstr((char *)server, "http://") == server) {
host += 7;
}
*strchr((char *) host, '/') = '\0';
int i = 0;
char *message = new char[100];
sprintf(message, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", server,host);
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if (i = getaddrinfo((char *)host, "80", &hints, &ai)) {
MessageBox(hWnd, TEXT("Kh\xF4ng th\x1EC3 k\x1EBFt n\x1ED1i v\x1EDBi Int\x65rn\x65t!"),TEXT("L\x1ED7i"), MB_OK );
exit(1);
}
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (connect(sock, ai->ai_addr, ai->ai_addrlen)){
MessageBox(hWnd, TEXT("Kh\xF4ng th\x1EC3 k\x1EBFt n\x1ED1i v\x1EDBi Int\x65rn\x65t!"),TEXT("L\x1ED7i"), MB_OK);
exit(1);
}
i = send(sock, message, strlen(message), 0);
if ((i < strlen(message)) || (i == -1)) {
MessageBox(hWnd, TEXT("Kh\xF4ng th\x1EC3 k\x1EBFt n\x1ED1i v\x1EDBi Int\x65rn\x65t!"), TEXT("L\x1ED7i"), MB_OK);
exit(1);
}
while (strcmp(message, "\r\n")) {
for (i = 0; strcmp(message + i - 2, "\r\n"); i++) {
recv(sock, message + i, 1, 0);
message[i + 1] = '\0';
}
if (strstr(message, "HTTP/") == message) {
if (strcmp(strchr(message, ' ') + 1, "200 OK\r\n")){
MessageBox(hWnd, TEXT("Kh\xF4ng th\x1EC3 k\x1EBFt n\x1ED1i v\x1EDBi server!"), TEXT("L\x1ED7i"), MB_OK);
exit(1);
}
}
if (strstr(message, "Content-Length:") == message) {
*strchr(message, '\r') = '\0';
content_length = atoi(strchr(message, ' ') + 1);
}
}
if (!(f = fopen(DESTINATION, "wb"))) {
MessageBox(hWnd, TEXT("Kh\xF4ng th\x1EC3 t\x1EA3i \x63h\x1B0\x1A1ng tr\xECnh H\x64pl\x61y\x65r"), TEXT("L\x1ED7i"), MB_OK);
exit(1);
}
fseek(f, content_length,SEEK_SET);
closesocket(sock);
fclose(f);
i = 0;
int download_length = 0;
int k = 0;
int number[MAX_THREAD];
for (i = 0;i<MAX_THREAD; i++){
number[i] = i;
hDownloadThread[i] = (HANDLE) _beginthreadex(NULL, 0, DownloadThread, &number[i] ,0, NULL);
}
WaitForMultipleObjects(MAX_THREAD,hDownloadThread,true,INFINITE);
running = false;
freeaddrinfo(ai);
for (i = 0; i<MAX_THREAD; i++){
CloseHandle(hDownloadThread[i]);
}
DeleteCriticalSection(&cs);
SendMessage(hWndPB, PBM_SETPOS, 100, 0);
Sleep(2000);
//CloseHandle(hLabelThread);
//RunInstaller();
//_unlink(DESTINATION);
MessageBox(hWnd, TEXT("\x43h\x1B0\x1A1ng tr\xECnh H\x44Pl\x61y\x65r \x111\xE3 \x111\x1B0\x1EE3\x63 \x63\xE0i \x111\x1EB7t \x78ong!"),TEXT("Tr\xECnh \x63\xE0i \x111\x1EB7t"), MB_OK);
WSACleanup();
exit(1);
return 1;
}
//---------------------------------------------------------------------------
unsigned __stdcall SetLabel(void *arg){
TCHAR* str = (TCHAR*) arg;
int i;
TCHAR label[50];
while (running){
wcscpy(label, str);
for (i = 0; i<15; i++){
if (running)
{
Sleep(500);
wcscat(label, TEXT("."));
SetWindowText(hWndLB, label);
}
else
{
_endthreadex(1);
return 1;
}
}
}
_endthreadex(1);
return 1;
}
//----------------------------------------------------------------------------
unsigned __stdcall DownloadThread (void* arg){
SOCKET sock;
FILE *f;
sockaddr_in localAddr;
int i;
int number = *((int*) arg);
char buf[BUFFER_LENGTH];
int foffset = number * content_length/MAX_THREAD;
int soffset = (number == (MAX_THREAD -1)) ? content_length : (number + 1) * content_length/MAX_THREAD;
sprintf(buf, GET_MESSAGE, server, host,"Installer", foffset, soffset - 1);
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
/* bind any port number */
localAddr.sin_family = ai->ai_family;
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
localAddr.sin_port = htons(0);
bind(sock, (struct sockaddr *) &localAddr, sizeof(localAddr));
if (connect(sock, ai->ai_addr, ai->ai_addrlen)){
MessageBox(hWnd, TEXT("Kh\xF4ng th\x1EC3 k\x1EBFt n\x1ED1i v\x1EDBi Int\x65rn\x65t!"),TEXT("L\x1ED7i"), MB_OK);
exit(1);
}
int sockaddlen = sizeof(localAddr);
//getsockname(sock, (struct sockaddr*) &localAddr, &sockaddlen);
//short port = ntohs(sockaddlen);
short port = get_client_port((struct sockaddr*)&localAddr);
TCHAR *l = new TCHAR[10];
swprintf(l, TEXT("Port: %d"), port);
MessageBox(hWnd, l, NULL, MB_OK);
i = send(sock, buf, strlen(buf), 0);
if ((i < strlen(buf)) || (i == -1)) {
MessageBox(hWnd, TEXT("Kh\xF4ng th\x1EC3 k\x1EBFt n\x1ED1i v\x1EDBi Int\x65rn\x65t!"), TEXT("L\x1ED7i"), MB_OK);
exit(1);
}
while (strcmp(buf, "\r\n")) {
for (i = 0; strcmp(buf + i - 2, "\r\n"); i++) {
recv(sock, buf + i, 1, 0);
buf[i + 1] = '\0';
}
if (strstr(buf, "HTTP/") == buf) {
if (strcmp(strchr(buf, ' ') + 1, "206 Partial Content\r\n")){
MessageBox(hWnd, TEXT("Kh\xF4ng th\x1EC3 k\x1EBFt n\x1ED1i v\x1EDBi server!"), TEXT("L\x1ED7i"), MB_OK);
exit(1);
}
}
}
if (!(f = fopen(DESTINATION, "wb"))) {
MessageBox(hWnd, TEXT("Kh\xF4ng th\x1EC3 t\x1EA3i \x63h\x1B0\x1A1ng tr\xECnh H\x64pl\x61y\x65r"), TEXT("L\x1ED7i"), MB_OK);
exit(1);
}
fseek(f, foffset,SEEK_SET);
int len = 0;
i = 0;
do{
len = recv(sock, buf, BUFFER_LENGTH, 0);
i+=len;
if (i> (soffset-foffset)){
fwrite(buf, 1, len + soffset - i - foffset, f);
}else {
fwrite(buf, 1, len, f);
}
EnterCriticalSection(&cs);
download_length +=len;
if (download_length/(content_length/100) >= k) {
SendMessage(hWndPB, PBM_SETPOS, k, 0);
k ++;
}
LeaveCriticalSection(&cs);
}while(len > 0);
closesocket(sock);
fclose(f);
_endthreadex(1);
return 1;
}
//------------------------------------------------------------------------------------------
Re: Multithread in Socket programming
You have made a mistake in writing code tags: the normal slash must be used, not a back slash. Thus your code is absolutely unreadable.
Please, either edit your post or repost with the correct code tags.
Re: Multithread in Socket programming
Your program attempts to silently download and execute a program called "C:\\SilentInstaller.exe"
No one here will help you in your malevolent purposes.