Jump to content

  • Log In with Google      Sign In   
  • Create Account

We need your help!

We need 1 more developer from Canada and 12 more from Australia to help us complete a research survey.

Support our site by taking a quick sponsored survey and win a chance at a $50 Amazon gift card. Click here to get started!


Psychopathetica

Member Since 05 Apr 2011
Offline Last Active Aug 23 2015 01:29 PM

Topics I've Started

TriangleStrips

15 July 2015 - 02:06 PM

Im trying to make a grid of quads starting with something small such as 2x2 to experiment working with TriangleStrips. It works, but it only works if I have one extra primitive in my drawing method, which doesnt make any sense. Clearly a 2x2 grid of quads has at least 8 triangle primitives, but putting 9 will draw all 8, whereas if I put 8, itll only draw 7 triangles. I started on the bottom of the grid, and worked my way towards the right till I reach the end, went up one row, and went from right to left. Can anyone explain why its only working with 9 rather than 8? Heres a sample of what I have setup:

void Create_Polygon()
{
    Vertex_List[0] = Create_Custom_Vertex(0, 200, 0, 1, D3DCOLOR_XRGB(255, 255, 255));
    Vertex_List[1] = Create_Custom_Vertex(0, 100, 0, 1, D3DCOLOR_XRGB(255, 255, 255));
    Vertex_List[2] = Create_Custom_Vertex(100, 200, 0, 1, D3DCOLOR_XRGB(255, 255, 255));
    Vertex_List[3] = Create_Custom_Vertex(100, 100, 0, 1, D3DCOLOR_XRGB(255, 255, 255));
    Vertex_List[4] = Create_Custom_Vertex(200, 200, 0, 1, D3DCOLOR_XRGB(255, 255, 255));
    Vertex_List[5] = Create_Custom_Vertex(200, 100, 0, 1, D3DCOLOR_XRGB(255, 255, 255));
    Vertex_List[6] = Create_Custom_Vertex(200, 0, 0, 1, D3DCOLOR_XRGB(255, 255, 255));
    Vertex_List[7] = Create_Custom_Vertex(100, 100, 0, 1, D3DCOLOR_XRGB(255, 255, 255));
    Vertex_List[8] = Create_Custom_Vertex(100, 0, 0, 1, D3DCOLOR_XRGB(255, 255, 255));
    Vertex_List[9] = Create_Custom_Vertex(0, 100, 0, 1, D3DCOLOR_XRGB(255, 255, 255));
    Vertex_List[10] = Create_Custom_Vertex(0, 0, 0, 1, D3DCOLOR_XRGB(255, 255, 255));
}

void Draw_Polygon()
{
    Device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
    Device->SetFVF(CUSTOM_VERTEX_FORMAT);
    Device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 9, Vertex_List, sizeof(CUSTOM_VERTEX));
}

Switching from DirectShow (Video) to DirectX Rendering Or Vice Versa

17 June 2015 - 03:42 PM

I'm trying to make the beginning of a game I'm working on, which normally, like any other game, consists of a video of a company logo intro, possibly a couple more company logos, an FMV intro, and the title which is done in the actual rendering rather than through videos. Right now I only have just a video of a company logo, and one measly textured quad in the actual rendering. I ran into what seems like an anomaly. With this current code, you dont see a video at all, but only hear the sound to it. Alt-Tabbing out and coming back you see a frame or two before it turns black again and continues to play. Also pressing escape goes directly into my DirectX rendering game loop just fine, although I had a black screen earlier. Pressing escape again exists the program:

#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <dshow.h>
#include <string>
using namespace std;

#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "strmiids.lib")
#pragma comment(lib, "quartz.lib")

#define WM_GRAPHEVENT    WM_USER

struct CUSTOM_VERTEX
{
    float X, Y, Z, RHW;
    DWORD Color;
    float TU, TV;
};

#define CUSTOM_VERTEX_FORMAT (D3DFVF_XYZRHW | D3DFVF_TEX1 | D3DFVF_DIFFUSE)

LPDIRECT3D9 D3D = NULL;
LPDIRECT3DDEVICE9 Device = NULL;
D3DDISPLAYMODE Display_Mode;
D3DPRESENT_PARAMETERS Screen;
HWND hWnd;
MSG msg;
bool Running;
CUSTOM_VERTEX Vertex_List[4];
HRESULT hr;
LPDIRECT3DTEXTURE9 Texture = NULL;

// DirectShow interfaces
IGraphBuilder*    g_pGraphBuilder = NULL;
IMediaControl*    g_pMediaControl = NULL;
IMediaEventEx*    g_pMediaEvent = NULL;
IMediaPosition*    g_pMediaPosition = NULL;
IVideoWindow* g_pVideoWindow;

BOOL        g_Looping = FALSE;
bool render = false;

CUSTOM_VERTEX Create_Custom_Vertex();
void Load_Texture();
void Render();
void Game_Loop();
void Main();
void Shutdown();
void DirectX_Initialize();
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
void directshow_load_media();
void OnGraphEvent();
void CleanUpDirectShow();

#define HELPER_RELEASE(x)   if (x != NULL) \
{ \
    x->Release(); \
    x = NULL; \
}

void DirectX_Initialize()
{
    D3D = Direct3DCreate9(D3D_SDK_VERSION);
    memset(&Screen, 0, sizeof(D3DPRESENT_PARAMETERS));
    Display_Mode.Width = 1920;
    Display_Mode.Height = 1080;
    Display_Mode.Format = D3DFMT_X8R8G8B8;
    Screen.Windowed = FALSE;
    Screen.BackBufferCount = 1;
    Screen.BackBufferWidth = Display_Mode.Width;
    Screen.BackBufferHeight = Display_Mode.Height;
    Screen.hDeviceWindow = hWnd;
    Screen.SwapEffect = D3DSWAPEFFECT_COPY;
    Screen.BackBufferFormat = Display_Mode.Format;
    D3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &Screen, &Device);

    Device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
    Device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
    Device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
    Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
    Device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
    Device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
    Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
    Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
    Device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
    Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
    Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
}

CUSTOM_VERTEX Create_Custom_Vertex(float X, float Y, float Z, float RHW, DWORD Color, float TU, float TV)
{
    CUSTOM_VERTEX Vertex;

    Vertex.X = X;
    Vertex.Y = Y;
    Vertex.Z = Z;
    Vertex.RHW = RHW;
    Vertex.Color = Color;
    Vertex.TU = TU;
    Vertex.TV = TV;

    return Vertex;
}

void Load_Texture(LPDIRECT3DTEXTURE9 *T, char *File_Path, int Transparency_Color)
{
    D3DXCreateTextureFromFileEx(Device, File_Path, 2048, 2048, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, D3DX_FILTER_POINT, D3DX_FILTER_POINT, Transparency_Color, NULL, NULL, T);
}

void Create_Polygon()
{
    Vertex_List[0] = Create_Custom_Vertex(0, 0, 0, 1, D3DCOLOR_XRGB(255, 255, 255), 0, 0);
    Vertex_List[1] = Create_Custom_Vertex(100, 0, 0, 1, D3DCOLOR_XRGB(255, 255, 255), 1, 0);
    Vertex_List[2] = Create_Custom_Vertex(0, 100, 0, 1, D3DCOLOR_XRGB(255, 255, 255), 0, 1);
    Vertex_List[3] = Create_Custom_Vertex(100, 100, 0, 1, D3DCOLOR_XRGB(255, 255, 255), 1, 1);
}

void Draw_Polygon()
{
    Device->SetFVF(CUSTOM_VERTEX_FORMAT);
    Device->SetTexture(0, Texture);
    Device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, Vertex_List, sizeof(CUSTOM_VERTEX));
}


void Render()
{
    Device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
    Device->BeginScene();
    Create_Polygon();
    Draw_Polygon();
    Device->EndScene();
    Device->Present(NULL, NULL, NULL, NULL);
}

void Game_Loop()
{
    while (Running == true)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) > 0)
        {
            if (WM_QUIT == msg.message) break;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            hr = Device->TestCooperativeLevel();
            if (hr != D3D_OK)
            {
                if (hr == D3DERR_DEVICELOST)
                {
                    Texture->Release();
                    g_pMediaControl->Pause();
                    Sleep(50); //Wait a bit so we don't burn through cycles for no reason
                }
                else if (hr == D3DERR_DEVICENOTRESET)
                {
                    
                    hr = Device->Reset(&Screen);
                    
                    if (SUCCEEDED(hr))
                    {
                        Device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
                        Device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
                        Device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
                        Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
                        Device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
                        Device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
                        Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
                        Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
                        Device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
                        Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
                        Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
                        Load_Texture(&Texture, "graphics\\stone.png", D3DCOLOR_XRGB(0, 0, 0));
                    }
                    if (render == false)
                    {
                        g_pMediaControl->Run();
                        continue;
                    }
                }
            }
            else if (hr == D3D_OK)
            {
                if (render == true)
                    Render();
            }
        }
    }
}

void directshow_load_media(const char *File_Name)
{
    CleanUpDirectShow();
    char buffer[MAX_PATH];
    string Result;
    GetModuleFileName(NULL, buffer, MAX_PATH);
    string startuppath = string(buffer);
    string filename = string(File_Name);
    startuppath = startuppath.substr(0, startuppath.find_last_of("\\/"));
    Result = startuppath + string("\\") + filename;
    const char *File_Path = Result.c_str();

    WCHAR *MediaFile = new WCHAR[strlen(File_Path) + 1];
    MultiByteToWideChar(CP_ACP, 0, File_Path, -1, MediaFile, strlen(File_Path) + 1);

    CoInitialize(NULL);
    CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder,(void**)&g_pGraphBuilder);
    
    g_pGraphBuilder->QueryInterface(IID_IMediaControl, (void**)&g_pMediaControl);
    g_pGraphBuilder->RenderFile(MediaFile, NULL);

    g_pGraphBuilder->QueryInterface(IID_IVideoWindow, (void**)&g_pVideoWindow);
    g_pVideoWindow->put_Visible(true);
    g_pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);
    g_pVideoWindow->put_Owner((OAHWND)hWnd);
    g_pVideoWindow->SetWindowPosition(0, 0, 1920, 1080);

    g_pGraphBuilder->QueryInterface(IID_IMediaEvent, (void**)&g_pMediaEvent);
    g_pMediaEvent->SetNotifyWindow((OAHWND)hWnd, WM_GRAPHEVENT, 0);

    g_pGraphBuilder->QueryInterface(IID_IMediaPosition, (void**)&g_pMediaPosition);
    
    g_pMediaControl->Run();
}

void CleanUpDirectShow()
{
    HELPER_RELEASE(g_pMediaPosition);
    HELPER_RELEASE(g_pMediaEvent);
    HELPER_RELEASE(g_pMediaControl);
    HELPER_RELEASE(g_pGraphBuilder);
}

void Main()
{
    DirectX_Initialize();
    directshow_load_media("videos\\Roman Software Logo.mpeg");
    Load_Texture(&Texture, "graphics\\stone.png", D3DCOLOR_XRGB(0, 0, 0));
    Running = true;
}

void Shutdown()
{
    Running = false;            
    CleanUpDirectShow();
    CoUninitialize();
    HELPER_RELEASE(Texture);
    HELPER_RELEASE(D3D);
    HELPER_RELEASE(Device);
    PostQuitMessage(0);
    HANDLE Process;
    Process = OpenProcess(PROCESS_ALL_ACCESS, true, GetCurrentProcessId());
    TerminateProcess(Process, 0);
}

void OnGraphEvent()
{
    long EventCode, Param1, Param2;
    while (g_pMediaEvent->GetEvent(&EventCode, &Param1, &Param2, 0) != E_ABORT)
    {
        switch (EventCode)
        {
        case EC_COMPLETE:
            if (!g_Looping)
            {
                if (g_pMediaControl != NULL)
                    g_pMediaControl->Stop();
                if (g_pMediaEvent != NULL)
                    g_pMediaEvent->SetNotifyWindow(NULL, 0, 0);
                render = true;
            }
            g_pMediaPosition->put_CurrentPosition(0);
            break;
        default:
            break;
        }
        g_pMediaEvent->FreeEventParams(EventCode, Param1, Param2);
    }
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_VREDRAW | CS_HREDRAW | CS_OWNDC, WindowProcedure, 0, 0, hInstance, NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, "GAME", NULL };
    RegisterClassEx(&wc);
    hWnd = CreateWindowEx(0, "GAME", "Game", WS_VISIBLE | WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, 330, 250, HWND_DESKTOP, NULL, hInstance, NULL);
    ShowWindow(hWnd, nCmdShow);
    Main();
    Game_Loop();
    return msg.wParam;
}

LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_DESTROY:
        Shutdown();
        break;
    case WM_KEYDOWN:
        if (wParam == VK_ESCAPE)
        {
            if (render == false)
            {
                if (g_pMediaControl != NULL)
                    g_pMediaControl->Stop();
                if (g_pMediaEvent != NULL)
                    g_pMediaEvent->SetNotifyWindow(NULL, 0, 0);
                render = true;
            }
            else
            {
                DestroyWindow(hWnd);
                return(0);
            }
            break;
            
        }
    case WM_GRAPHEVENT:
        if (g_pGraphBuilder != NULL)
        {
            if (render == false)
            {
                OnGraphEvent();
                break;
            }
        }
    default:
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    return 0;
}

Now here is when it gets weird. If I reset the DirectX device like so:

void Main()
{
    DirectX_Initialize();
    directshow_load_media("videos\\Roman Software Logo.mpeg");
    Load_Texture(&Texture, "graphics\\stone.png", D3DCOLOR_XRGB(0, 0, 0));
    hr = Device->Reset(&Screen);

    if (SUCCEEDED(hr))
    {
        Device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
        Device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
        Device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
        Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
        Device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
        Device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
        Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
        Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
        Device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
        Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
        Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
    }
    Running = true;
}

the video comes up in my window just fine, however, I can't escape it, and it only shows a freeze frame after pressing the escape key. I couldn't for the life of me figure out how I can prevent it from freezing and going into my renderer.

 

This is the weirder part. If I load the texture file after I reset the device, its a black screen again thats escapable. And if I load the texture before before resetting the device (like the code above), it runs in the window just fine, yet it freezes when I attempt to escape out of it. Also note this whole time I have not had the video playing in a separate ActiveMovie window at all. It was all running within my one window. How can I have the video play without having to reset the directx device afterwards, and be escapable to the actual rendering code? Thanks in advance.


Get External IP Address Without 3rd Party Websites

04 December 2014 - 12:59 PM

Ive been doing some research on how to pull this off, and come to find no solutions anywhere online. Winsock alone will only retrieve your local ip address and not your external ip address. Other solutions and recommendations were to rely on 3rd party websites such as whatismyip.com. Scripting was another way. And also found that it is possible to do in C++ but is very difficult and you would need to create your own function. Even though this has been mentioned, the solutions were not presented at all. And what would really suck is if i were to rely on assembly code. Could anyone point me in the right direction on the steps needed to pull this off without resorting to 3rd party websites? Thanks in advance

Switching from CreateThread() to Thread

23 November 2014 - 06:34 PM

I made a simple chat program using a simple console window, but have one problem. Originally both my client and server were using CreateThread(), but saw some more benefits of using the thread header so I began switching it. I did the client first and so far everything works with no problems. But then I tried the server end, and the program went haywire in the loop. With no client open at all, simply running the server kept accepting clients and disconnecting clients over and over rapidly. Its suppose to pause at accept and bare in mind, no client was open at all!

After careful debugging and putting those couple of lines of code back the way it was back to CreateThread(), I found simply having #include <thread> uncommented was making my loop go haywire. I wasnt even doing anything with the header. Whats making my program act that way from that thread header? Thanks in advance

Issue With Simple Client To Server Chat Program

17 November 2014 - 03:45 PM

Hey guys. I'm a little bit new to winsock programming in C++ and ran into an issue. The server works fine with one client up. And once I get another client up, the server can receive one or two messages from the first client before it ultimately is no longer receiving messages from that client, but is able to receive unlimited messages from the 2nd client. This holds true if I were to open a 3rd client, the serve is able to pick up a message or two from the 2nd client until it no longer receives messages from that client, while its able to receive unlimited messages from the 3rd client. I can't for the life of me figure out whats going on but its the closest I've ever gotten to a simple chat program with this code I whipped up. Bare in mind I eliminated the error handling to make it easier to understand for now until I get it working.

Server code:
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>#
include <string>
using namespace std;
#pragma comment (lib, "Ws2_32.lib")
#define IP_ADDRESS "192.168.56.1"
#define DEFAULT_PORT "3504"
#define DEFAULT_BUFLEN 2024
const char option_value = 1;
//Function Prototypes
DWORD WINAPI ProcessClient(LPVOID Parameter);
int main();
WSADATA wsaData;
struct addrinfo hints;
struct addrinfo *server = NULL;
SOCKET server_socket = INVALID_SOCKET;
SOCKET client_socket= INVALID_SOCKET;
int num_clients = 0;
string msg = "";
char tempmsg[DEFAULT_BUFLEN] = "";

DWORD WINAPI ProcessClient(LPVOID Parameter)
{	
    //Session	
    cout << "Client #" << num_clients << " Accepted" << endl;	
    num_clients++;	
    while (1)	
    {			
        memset(tempmsg, 0, DEFAULT_BUFLEN);			
        if (client_socket != 0)			
        {				
            int iResult = recv(client_socket, tempmsg, DEFAULT_BUFLEN, 0);
            if (iResult > 0)				
            {					
                if (strcmp("", tempmsg))
		    msg = tempmsg;					
                cout <<  msg.c_str() << endl << endl;
            }		
        }	
    }	
    return 0;
}

int main()
{	
    //Initialize Winsock	
    cout << "Intializing Winsock..." << endl;	
    WSAStartup(MAKEWORD(2, 2), &wsaData);	

    //Setup hints	
    ZeroMemory(&hints, sizeof(hints));	
    hints.ai_family = AF_INET;	
    hints.ai_socktype = SOCK_STREAM;	
    hints.ai_protocol = IPPROTO_TCP;	
    hints.ai_flags = AI_PASSIVE;	

    //Setup Server	
    cout << "Setting up server..." << endl;	
    getaddrinfo(static_cast<LPCTSTR>(IP_ADDRESS), DEFAULT_PORT, &hints, &server);
	
    //Create a listening socket for connecting to server	
    cout << "Creating server socket..." << endl;	
    server_socket = socket(server->ai_family, server->ai_socktype, server->ai_protocol);	

    //Setup socket options	
    setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &option_value, sizeof(int)); //Make it possible to re-bind to a port that was used within the last 2 minutes	
    setsockopt(server_socket, IPPROTO_TCP, TCP_NODELAY, &option_value, sizeof(int));     //Used for interactive programs	

    //Assign an address to the server socket.	
    cout << "Binding socket..." << endl;	
    bind(server_socket, server->ai_addr, (int)server->ai_addrlen);	

    //Listen for incoming connections.	
    cout << "Listening..." << endl;	
    listen(server_socket, SOMAXCONN);	
    while (1)	
    {		
        while (client_socket = accept(server_socket, NULL, NULL))		
        {			
            DWORD threadID;			
            CreateThread(NULL, 0, ProcessClient, (LPVOID)client_socket, 0, &threadID);		    
        }	
    }	

    //Close listening socket	
    closesocket(server_socket);	

    //Close client socket	
    closesocket(client_socket);	

    //Clean up Winsock	
    WSACleanup();	
    cout << "Program has ended successfully" << endl;	
    system("pause");	
    return 0;
}
The client code isnt necessary, as the problem lies in here.

In attempt two to try and get it working, I tried making the client_socket an array. Although it sort of works, it works in a very bad way. For example, if I have client 1 and client 2 log on afterwards. The server can receive a message from client 1 but cant from client two until it has received a message from client 1, and vice versa. As though it gets stuck in recv() in the middle of a for loop in the thread. I have no idea on how to fix any of this and any help will be appreciated. Thanks in advance.

PARTNERS