基于socket的多线程(阻塞模式)聊天室

//服务端   服务端转发消息    多线程阻塞模式

#include< stdio.h >

#include< stdlib.h >
#include< windows.h >
#include< winsock.h >
#include <vector>
#include <afx.h>
#include <algorithm>


using namespace std;


#pragma comment( lib, "ws2_32.lib" )


#define PORT 2048
#define BACKLOG 10
#define TRUE 1




vector<int> all_user;


struct ip_st 
{
char cli_ip[50];
SOCKET cli_so;
};


CString s_user;
CString temp;
char tt[20];
DWORD _stdcall recv_f(LPVOID lp)
{
ip_st* so = new ip_st;
memcpy(so,lp,sizeof(ip_st));
CString analyse_data;
CString trans_to;
USES_CONVERSION;
while(1)
{
char buf[100];
memset(buf,0,100);
int bb = recv(so->cli_so,buf,100,0);
if( bb != -1)
{
if (bb == 0)
{
printf( "%s  离线!\n",so->cli_ip);
closesocket(so->cli_so);
delete so;
return 0;
}else
{


//分析数据
analyse_data  = buf;
int an_lab = analyse_data.Find(L":");
int rr = -1;
if (an_lab != -1)
{
analyse_data = analyse_data.Left(an_lab);
if (s_user.Find(analyse_data) != -1)
{
int a = _wtoi(analyse_data);


analyse_data  = buf;
analyse_data = analyse_data.Mid(an_lab+1,analyse_data.GetLength()-an_lab);


printf("%d对%d说:%s\n",so->cli_so,a,T2A(analyse_data));


if (send(a,T2A(analyse_data),strlen(T2A(analyse_data)),0) != -1)
{
rr = send(so->cli_so,"服务器收到数据并转发成功!\n",sizeof("服务器收到数据并转发成功!\n"),0);
if (rr != -1)
{
printf("反馈客户端成功!\n");
}
}
}
}



发送用户列表


s_user = L"";


for (vector<int>::iterator it= all_user.begin();it != all_user.end();it++)
{
if (*it == so->cli_so)
{
temp.Format(L"自己在线,",*it);
}else
{
temp.Format(L"%d:用户在线,",*it);
}

s_user += temp;
}



rr = send(so->cli_so,T2A(s_user),strlen(T2A(s_user)),0);
if (rr == -1)
{
printf("用户列表发送失败!");
}
}

}else
{
printf( "%s  意外掉线!\n",so->cli_ip);
vector<int>::iterator findit = find(all_user.begin(),all_user.end(),so->cli_so);
all_user.erase(findit);


for (vector<int>::iterator it = all_user.begin();it != all_user.end();it++)
{
memset(tt,0,20);
sprintf(tt,"%d掉线",so->cli_so);
send(*it,tt,strlen(tt),0);
}


s_user = L"";


for (vector<int>::iterator it= all_user.begin();it != all_user.end();it++)
{
if (*it == so->cli_so)
{
temp.Format(L"自己在线,",*it);
}else
{
temp.Format(L"%d:用户在线,",*it);
}


s_user += temp;
}


for (vector<int>::iterator it = all_user.begin();it != all_user.end();it++)
{
send(*it,T2A(s_user),strlen(T2A(s_user)),0);
}



closesocket(so->cli_so);
delete so;
return 0;
}
}
return 0;
}




int sin_size;
int iServerSock;








DWORD __stdcall acc(LPVOID lp)
{
int iClientSock;
struct sockaddr_in ClientAddr;

while( TRUE )
{
sin_size = sizeof( struct sockaddr_in );
iClientSock = accept( iServerSock, ( struct sockaddr * )&ClientAddr, &sin_size );


USES_CONVERSION;


if( iClientSock == -1 )
{
printf( "accept调用失败!\n" );
WSACleanup( );
exit( 0 );
}else
{
all_user.push_back(iClientSock);
s_user = L"";


for (vector<int>::iterator it= all_user.begin();it != all_user.end();it++)
{
temp.Format(L"%d:用户在线,",*it);


s_user += temp;
}


for (vector<int>::iterator it = all_user.begin();it != all_user.end();it++)
{
send(*it,T2A(s_user),strlen(T2A(s_user)),0);
}
}


printf( "服务器连接到%s\n", inet_ntoa(ClientAddr.sin_addr));
ip_st temp;
temp.cli_so = iClientSock;
sprintf(temp.cli_ip,"%s",inet_ntoa( ClientAddr.sin_addr ));




CreateThread(0,0,recv_f,(LPVOID)&temp,0,0);
}
return 0;
}




void main( void )
{




char *buf = "hello, world!\n";




struct sockaddr_in ServerAddr;




WSADATA WSAData;


if( WSAStartup( MAKEWORD( 1, 1 ), &WSAData ) )//初始化
{
printf( "initializationing error!\n" );
WSACleanup( );
exit( 0 );
}


if( ( iServerSock = socket( AF_INET, SOCK_STREAM, 0 ) ) == INVALID_SOCKET )
{
printf( "创建套接字失败!\n" );
WSACleanup( );
exit( 0 );
}


ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons( PORT );//监视的端口号
ServerAddr.sin_addr.s_addr =  inet_addr("127.0.0.1");//本地IP
memset( & ( ServerAddr.sin_zero ), 0, sizeof( ServerAddr.sin_zero ) );




if( bind( iServerSock, ( struct sockaddr * )&ServerAddr, sizeof( struct sockaddr ) ) == -1 )
{
printf( "bind调用失败!\n" );
WSACleanup( );
exit( 0 );
}


if( listen( iServerSock, BACKLOG ) == -1 )
{
printf( "listen调用失败!\n" );
WSACleanup( );
exit( 0 );
}
CreateThread(0,0,acc,0,0,0);
system("pause");


}




//客户端

#include< stdio.h >
#include< stdlib.h >
#include< windows.h >
#include< winsock.h >
#include<string>
#include <afx.h>


using namespace std;


#pragma comment( lib, "ws2_32.lib" )


#define PORT 2048
#define BACKLOG 10
#define TRUE 1
#define MAXDATASIZE 100


SOCKET iClientSock;


std::string ss_list;


DWORD __stdcall recv_msg(LPVOID lp)
{
char buf[100];
while(1)
{
memset(buf,0,100);
int return_val = recv(iClientSock,buf,100,0);
if (return_val != -1)
{
if (strlen(buf) >0)
{
printf("%s\n",buf);
}

}else
{
printf("服务器断开连接!\n");
return 0;
}

}
return 0;
}


void main( void )
{




char buf[ MAXDATASIZE ];
struct sockaddr_in ServerAddr;
int numbytes;
WSADATA WSAData;




WORD wVersionRequested;
WSADATA wsaData;
int err;
 
wVersionRequested = MAKEWORD( 2, 2 );
 
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ){return;}
 
if ( LOBYTE( wsaData.wVersion ) != 2 ||HIBYTE( wsaData.wVersion ) != 2 )
{
WSACleanup( );
return; 
}




if( ( iClientSock = socket(AF_INET, SOCK_STREAM,0)) == INVALID_SOCKET )
{
printf( "创建套接字失败!\n" );
WSACleanup( );
exit( 0 );
}


ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons( PORT );
// ServerAddr.sin_addr = *( ( struct in_addr * )he->h_addr );
ServerAddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );//记得换IP
memset( &( ServerAddr.sin_zero ), 0, sizeof( ServerAddr.sin_zero ) );


if( connect(iClientSock,( struct sockaddr * ) & ServerAddr, sizeof( struct sockaddr ) ) == -1 )
{
printf( "connect失败!" );
WSACleanup( );
exit( 0 );
}
//HANDLE had1 = CreateThread(0,0,send_msg,(LPVOID)&iClientSock,0,0);


HANDLE had = CreateThread(0,0,recv_msg,0,0,0);


while(TRUE)
{
char buf[100];
memset(buf,0,100);
scanf("%s",&buf);
int lab = send(iClientSock,buf,strlen(buf),0);
if (lab == strlen(buf))
{
printf("发送 %d 个字节成功!\n",lab);
}


}


system("pause");
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值