您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關基于TCP和多線程的聊天框架代碼是什么,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
/**//****************************************************
【服務端】基于TCP,多線程的聊天框架代碼
評注:非常完整
******************************************************/
#include "stdafx.h"
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
/**//*****************定義客戶端連接上后的聊天線程函數************/
DWORD WINAPI ClientThread(LPVOID lpParam)
{
SOCKET sock = (SOCKET)lpParam;//定義連接客戶端的套接字
char szBuff[2048];//定義接收緩沖區
char szMessage[2048];//定義發送的消息
int ret,
nLeft,
idx;//nLeft,idx用以控制寫緩沖的數據,以保證數據寫入正確
//提示輸入exit退出聊天
puts("輸入\"exit\"可退出聊天\n");
//進入數據傳輸循環,即聊天
//缺陷是只能一人一句來回對話
while(1)
{
/**////////////////////////// 接收 /////////////////
ret = recv(sock,szBuff,2048,0);
if(ret == 0)
break;
else if(ret == SOCKET_ERROR)
{
printf("recv() failed:%d\n",WSAGetLastError());
break;
}
szBuff[ret] = '\0';
//判斷對方發過來的是否為exit退出命令,若是則退出聊天繼續監聽
if(!strcmp(szBuff,"exit"))
{
printf("對方已經停止聊天!\n");
printf("服務器正在監聽");
break;
}
printf("客戶:%s\n",szBuff);//在控制臺打印客戶的聊天語句
/**/////////////////////////// 回復 //////////////////
printf("發送消息:");
//服務器輸入數據回答客戶
gets(szMessage);
//若發送為空,則傳送‘不說話’三字,并提示
if(strlen(szMessage)==0)
{
printf("發送不能為空哦\n");
strcpy(szMessage,"不說話!");
}
//傳送數據
nLeft = strlen(szMessage);
idx = 0;
//確保寫進所有數據
while(nLeft>0)
{
ret = send(sock,&szMessage[idx],nLeft,0);
if(ret == 0)
break;
else if(ret == SOCKET_ERROR)
{
printf("send error!%d\n",WSAGetLastError());
break;
}
nLeft-=ret;
idx +=ret;
}
//判斷szMessage是否為exit命令,若是則退出聊天繼續監聽
if(!strcmp(szMessage,"exit"))
{
printf("連接正在斷開!\n");
printf("服務器繼續監聽\n");
break;
}
}
return 0;
}
//主函數
int main(int argc, char* argv[])
{
WSADATA wsd;//定義WINSOCK32消息結構體
SOCKET sServSock;//服務器端的套接字
SOCKET sConns;//服務器的各連接
HANDLE hThread;//定義處理客戶連接的縣城
DWORD dwThreadId;//定義線程ID
char szAddress[128];//監聽的地址
struct hostent *host = NULL;//定義本地地址指針
sockaddr_in local,
client;//分別定義本地,客戶端的地址結構
int nSockErr;//定義出錯信息
printf("請你輸入監聽地址(格式如202.204.118.138):");
gets(szAddress);
int nAddrLen = sizeof(client);//得到地址結構長度
//初始化Winsock32庫
if(WSAStartup(MAKEWORD(2,2),&wsd) != 0)
{
printf("failed to load winsock!\n");
return 1;
}
//建立socket對象
sServSock = socket(AF_INET,SOCK_STREAM,IPPROTO_IP);//流套接字,面向連接
//為socket分配端口地址監聽
local.sin_family = AF_INET;
local.sin_port = htons(5150);//監聽端口
//若地址出錯則監聽本機地址
if((local.sin_addr.s_addr = inet_addr(szAddress))
==INADDR_NONE)
{
puts("所輸入的地址不正確,本服務將使用本機地址!");
//得到主機名
if(gethostname(szAddress,sizeof(szAddress))==SOCKET_ERROR)//得到本機的域名,名稱
{
puts("Can't getting local host name.");
}
//通過主機名得到主機IP地址
host = gethostbyname(szAddress);//得到本地ip
if(host)
CopyMemory(&local.sin_addr,host->h_addr_list[0],
host->h_length);
else
{
printf("gethostbyname() failed:%d\n",WSAGetLastError());
Sleep(5000);
return 1;
}
}
//將套接字綁定到本機地址local上
if(bind(sServSock,(LPSOCKADDR)&local,sizeof(local))==SOCKET_ERROR)
{
nSockErr = WSAGetLastError();
printf("bind error:%d!\n", nSockErr);
return 1;
}
//監聽客戶連接請求
if(listen(sServSock,5)==SOCKET_ERROR)
{
nSockErr =WSAGetLastError();
printf("listen error:%d\n", nSockErr);
return 1;
}
//提示狀態
printf("服務器啟動成功!\n");
printf("服務器正在監聽\n");
//進入處理連接循環
while(1)
{
//若有客戶連接,則接受連接
sConns = accept(sServSock,(struct sockaddr *)&client,&nAddrLen);
if(sConns == INVALID_SOCKET)
{
nSockErr = WSAGetLastError();
printf("accept error %d\n",nSockErr);
break;
}
//連接正確則提示可以開始聊天
printf("%s:%d連接到了本服務,現在可以聊天了.\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
//創建一個線程用于聊天
hThread = CreateThread(NULL,0,ClientThread, (LPVOID)sConns,0,&dwThreadId);
if(hThread == NULL)
{
printf("CreateThread() failed %d\n",GetLastError());
break;
}
//聊天結束關閉聊天線程,繼續監聽
CloseHandle(hThread);
}
closesocket(sServSock);
WSACleanup();
return 0;
}
/**//***********************************************************
客戶端
************************************************************/
#include "stdafx.h"
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
int main(int argc,char **argv)
{
WSADATA wsd;//定義winsock32信息結構
SOCKET sClient;//定義本地套接字
char szBuffer[2048];//定義接受的緩沖
char szMessage[2048];//發送的消息
char szServer[128];//連接的服務器地址,IP地址
int ret;
struct sockaddr_in server;//定義連接的服務器地址
struct hostent *host =NULL;//定義地址
//提示輸入連接的服務器地址
printf("請輸入連接的服務器IP地址(如:202.204.118.138):");
gets(szServer);
//初始winsock庫
if(WSAStartup(MAKEWORD(2,2),&wsd)!=0)
{
printf("Failed to load Winsock library!\n");Sleep(5000);
return 1;
}
// strcpy(szMessage,"我是***");
//建立socket對象
sClient = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(sClient == INVALID_SOCKET)
{
printf("socket() failed :%d\n",WSAGetLastError());Sleep(5000);
return 1;
}
//定義服務器地址以發送信息
server.sin_family = AF_INET;
server.sin_port = htons(5150);//端口
server.sin_addr.s_addr = inet_addr(szServer);
//若沒有地址,則將地址設置為本機地址
if(server.sin_addr.s_addr == INADDR_NONE)
{
puts("所輸入服務器地址不正確,本將使用本機地址!");
//得到主機名
if(gethostname(szServer,sizeof(szServer))==SOCKET_ERROR)//得到本機的域名,名稱
{
puts("Can't getting local host name.");
}
//通過主機名得到IP
host = gethostbyname(szServer);
if(host == NULL)
{
printf("Unable to resolve server:%s\n",szServer);Sleep(5000);
return 1;
}
CopyMemory(&server.sin_addr,host->h_addr_list[0],host->h_length);
}
//建立連接
if(connect(sClient,(struct sockaddr *)&server,sizeof(server))==SOCKET_ERROR)
{
printf("connect() failed:%d\n",WSAGetLastError());
Sleep(5000);
return 1;
}
//提示當前狀態
puts("連接成功,現在可以聊天了!\n");
puts("輸入\"exit\"可退出聊天\n");
//進入聊天狀態
while(1)
{
/**/////////發送
printf("發送消息:");
//寫入發送信息
gets(szMessage);
if(strlen(szMessage)==0)
{
printf("發送不能為空哦\n");
strcpy(szMessage,"不說話!");
}
//發送信息
ret = send(sClient,szMessage,strlen(szMessage),0);
if(ret == 0)
{
}
else if(ret == SOCKET_ERROR)
{
printf("send() failed: %d\n",WSAGetLastError());
Sleep(5000);
}
//判斷輸入信息是否為exit命令,若是則退出
if(!strcmp(szMessage,"exit"))
{
printf("你已經退出了聊天!");
break;
}
// printf("send %d byte\n",ret);
/**//////接收回復的信息
ret = recv(sClient,szBuffer,2048,0);
if(ret == 0)
;
else if(ret == SOCKET_ERROR)
{
printf("recv()failed:%d\n",WSAGetLastError());
}
//設置接收得到的字符串,并打印
szBuffer[ret] = '\0';
if(!strcmp(szBuffer,"exit"))
{
printf("服務器已經停止聊天!");
break;
}
printf("服務器:%s\n",szBuffer);
}
//關閉套接字
closesocket(sClient);
//清空winsock環境
WSACleanup();
return 0;
}
以上就是基于TCP和多線程的聊天框架代碼是什么,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。