Maverick_Cool
asked on
Access violation reading location while using CSocket across threads....
I am modify a VC++ web server code(small),
It throws access violation in sockcore.cpp while starting a new threading, Myapp is non mfc, but i have headers file to access CString and CSocket.
Is there a solution.
I am posting my code.
It throws access violation in sockcore.cpp while starting a new threading, Myapp is non mfc, but i have headers file to access CString and CSocket.
Is there a solution.
I am posting my code.
#include "stdafx.h"
#include <atlstr.h>
//process.h
#include <afxsock.h>
CString Path;
UINT NewThread (LPVOID p);
CString MIME(CString GetEX);
int Connections;
bool doRun = true;
CSocket Listener;
void webserver()
{
char TPath[50];
//cout << "Enter the path to your index file" << endl;
//cout << "Ex: C:\\html\\MicahServer" << endl;
//cin >> TPath;
//Path.Format("%s", &TPath);
Path = "c:\\webserver\\root";
AfxSocketInit();
//CSocket Listener;
int Code = Listener.Create(80); //Create socket
if( Code == 0 )
{
// cout << "Error creating Socket." << endl; //Get this usually if something is already listening on Port 80.
}
Listener.Listen();
//cout << "Listening..." << endl;
while(1)
{
CSocket pConn;
Listener.Accept(pConn); //Accept on pConn.
Connections++;
AfxBeginThread(NewThread, (LPVOID) pConn.Detach()); //Start new thread.
}
}
UINT NewThread (LPVOID p)
{
CSocket TheConn;
TheConn.Attach((SOCKET)p);
CSocketFile file(&TheConn);
CArchive arIn(&file, CArchive::load);
CArchive arOut(&file, CArchive::store);
CString Request;
CString RFile;
int First = 0;
do {
arIn.ReadString(Request); //Read incomming data line by line.
//cout << (LPCTSTR)Request << endl;
if (First == 0 ){
RFile = Request.Mid(4, Request.Find(L" ", 4) - 4);
First = 1;
}
} while (Request != "");
CString Temp;
CString Type;
CString GetEX;
CString HisIP;
CString Varis;
unsigned int Port;
TheConn.GetPeerName(HisIP, Port); //Get Clients IP and Port.
// cout << endl << "Connected to " << (LPCSTR)HisIP <<", on port " << Port << endl;
GetEX = RFile.Mid(RFile.Find(L".", 1) + 1);
if( GetEX.Find(L"?",1)!=-1){ // Remove any variables the Client tried to send in the request
Varis = GetEX.Mid(GetEX.Find(L"?",1) +1);
GetEX = GetEX.Mid(0, GetEX.Find(L"?"));
RFile = RFile.Mid(0, RFile.Find(L"?"));
}
Type.Format(MIME(GetEX)); // Get the MIME Type
if( RFile == "/" ) { //If only recived a / look for index file.
CFile Filer;
CString TFile;
CFileException peError;
RFile.Format(L"\\index.html");
TFile.Format(L"%s%s",Path, RFile);
if (!Filer.Open(TFile, CFile::shareDenyNone, &peError)){
RFile.Format(L"\\index.php");
TFile.Format(L"%s%s",Path, RFile);
if (!Filer.Open(TFile, CFile::shareDenyNone, &peError)){
RFile.Format(L"\\index.htm");
TFile.Format(L"%s%s",Path, RFile);
if (!Filer.Open(TFile, CFile::shareDenyNone, &peError)){
RFile.Format(L"\\index.htm");
TFile.Format(L"%s%s",Path, RFile);
}
}
}
}
Temp.Format(L"%s", (LPCSTR)(LPCTSTR)RFile);
RFile.Format(L"%s%s", Path, Temp);
// cout << (LPCSTR)RFile << " " << (LPCSTR)Type << endl;
CString AllData;
int FLen;
char *FileData[8193];
CFile File;
CFileException pError;
if (File.Open(RFile, CFile::shareDenyNone, &pError))
{
FLen = File.GetLength();
AllData.Format(L"HTTP/1.1 200 OK\nContent-Type: %s\nServer: TCS MicahServer 4.0a\nContent-Length: %d\nConnection: close\n\n", Type, FLen); //Header
TheConn.Send(AllData, AllData.GetLength(), 0);
UINT nRead;
while ((nRead = File.Read(FileData, 8192)))// File.Read returns the number of bytes successfully read.
TheConn.Send(FileData, nRead, 0); // Send data
}
else
{
AllData.Format(L"HTTP/1.1 404 Object Not Found\nServer: TCS MicahServer 4.0a\nConnection: close\n\n");
int AllSize;
AllSize = AllData.GetLength();
TheConn.Send(AllData, AllSize, 0); //Send data
}
return 0;
}
CString MIME(CString GetEX)
{
GetEX.MakeLower();
if ( GetEX == "gif" ){
return "image/gif";
}
if ( GetEX == "jpg" ){
return "image/jpeg";
}
if ( GetEX == "zip" ){
return "aplication/zip";
}
if ( GetEX == "exe" ){
return "aplication/exe";
}
if ( GetEX == "asp" ){
return "text/asp";
}
if ( GetEX == "bmp" ){
return "image/bmp";
}
if ( GetEX == "mov" ){
return "video/quicktime";
}
if ( GetEX == "mp3" ){
return "video/mpeg";
}
if ( GetEX == "mpeg" ){
return "video/mpeg";
}
if ( GetEX == "txt" ){
return "text/plain";
}
if ( GetEX == "cab" ){
return "application/octet-stream";
}
else {
return "text/html";
}
}
ASKER
Error 2 error C2440: 'initializing' : cannot convert from 'SOCKET' to 'SOCKET *'
Sorry, try:
CSocket TheConn;
if(p) {
SOCKET * _p = (SOCKET*)p;
TheConn.Attach(*_p);
}
else {
AfxMessageBox(_T("p is NULL"));
}
...also on line 44 I believe you need to call it as in the code snippet below. I don't have access to a compiler at the moment so please let me know if it fails and I'll take a look at it tomorrow.
AfxBeginThread(NewThread, (LPVOID)&pConn.Detach());
ASKER
Unhandled exception at 0x00403d40 in xxxxxxxx.exe: 0xC0000005: Access violation reading location 0x00000d84.
ASKER
changing line 44:
Error 1 error C2102: '&' requires l-value
Error 1 error C2102: '&' requires l-value
Ok, sorry for the inconvenience, I will follow up tomorrow.
The problem is the second parameter of the thread function is a void pointer, whereas the Detach function returns a SOCKET structure, if you like try also this also line 44:
The problem is the second parameter of the thread function is a void pointer, whereas the Detach function returns a SOCKET structure, if you like try also this also line 44:
SOCKET _s = pConn.Detach();
AfxBeginThread(NewThread, (LPVOID)&_s);
ASKER
well when is was separate console application it was working properly,
some thing to do with wnd class registration and hooking
some thing to do with wnd class registration and hooking
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
>>>> char *FileData[8193];
That is an array of char pointers. You were using it in CFile::Read which expects an array of chars (and not an array of pointers). Your code will work nevertheless as you pass the same array to CAsyncSocket::Send which also expects a char buffer. Since a pointer array was bigger in size than a char array the wrong type doesn't harm but all in all it is a rather bad code with poor initializing and risky casts and you will have bad luck if you don't make some fundamental overwork.
>>>> while(1)
>>>> {
>>>>
>>>> CSocket pConn;
>>>> Listener.Accept(pConn); //Accept on pConn.
>>>> Connections++;
>>>> AfxBeginThread(NewThread, (LPVOID) pConn.Detach()); //Start new thread.
>>>>
>>>> }
In that loop you create a new CSocket and call Accept. Then, you start a new thread passing the new socket handle. But after that call (and before the new thread could be alive) the loop cycle ends and the CSocket pConn runs out of scope. That means that the destructor was called and the pConn was disconnected. That makes the passed socket handle invalid as well.
You need to define the CSocket before the loop and you MUST have some way how to break the infinite loop somehow (e. g. by accepting a client which invokes a stop request).
That is an array of char pointers. You were using it in CFile::Read which expects an array of chars (and not an array of pointers). Your code will work nevertheless as you pass the same array to CAsyncSocket::Send which also expects a char buffer. Since a pointer array was bigger in size than a char array the wrong type doesn't harm but all in all it is a rather bad code with poor initializing and risky casts and you will have bad luck if you don't make some fundamental overwork.
>>>> while(1)
>>>> {
>>>>
>>>> CSocket pConn;
>>>> Listener.Accept(pConn); //Accept on pConn.
>>>> Connections++;
>>>> AfxBeginThread(NewThread, (LPVOID) pConn.Detach()); //Start new thread.
>>>>
>>>> }
In that loop you create a new CSocket and call Accept. Then, you start a new thread passing the new socket handle. But after that call (and before the new thread could be alive) the loop cycle ends and the CSocket pConn runs out of scope. That means that the destructor was called and the pConn was disconnected. That makes the passed socket handle invalid as well.
You need to define the CSocket before the loop and you MUST have some way how to break the infinite loop somehow (e. g. by accepting a client which invokes a stop request).
ASKER
i couldn't make it work...the problem was use of mfc lib filesin non mfc app. CSocket works poorly with threads when its not able find app handler
>>> CSocket works poorly with threads when its not able find app
You can pass a pointer to your app to the thread, e. g. by using a structure like
struct ThreadData
{
SOCKET sock;
MyApp * ptrApp;
};
in myapp.cpp
BOOL MyApp::createThreads()
{
for (int i = 0; i < MAX_THREADS; ++i)
{
ThreadData * pt = new ThreadData;
pt->sock = getSocketForThread(i);
pt->sock = this; // here set the application pointer
HANDLE h = _beginthread(threadFunc, 0, pt); // create thread and pass ThreadData
// save thread resources
myThreads.push_back(pair<T hreadData* , HANDLE>(pt, h));
}
}
You can pass a pointer to your app to the thread, e. g. by using a structure like
struct ThreadData
{
SOCKET sock;
MyApp * ptrApp;
};
in myapp.cpp
BOOL MyApp::createThreads()
{
for (int i = 0; i < MAX_THREADS; ++i)
{
ThreadData * pt = new ThreadData;
pt->sock = getSocketForThread(i);
pt->sock = this; // here set the application pointer
HANDLE h = _beginthread(threadFunc, 0, pt); // create thread and pass ThreadData
// save thread resources
myThreads.push_back(pair<T
}
}
Open in new window