c语言socket简易聊天室

本人新手,写一篇文章纪念一下-.-  

喜不喜欢都可以说,喷我就请联系我再喷呗,如果在评论下面喷多不好-。-

这一个是使用服务器作为消息转发的中介,使用了队列,废话不多说直接上代码:

以下是服务器端代码:

//TcpServer.cpp


#include <stdio.h>


#include<queue>


#include <winsock2.h>


#include<string.h>




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


using namespace std;


DWORD WINAPI ListenThread(LPVOID);//接收每一个信息到队列中


DWORD WINAPI SendThread();//发送消息队列中的每一个消息


DWORD WINAPI oneThread(LPVOID lpParameter);//总线程


DWORD WINAPI acceptThread(LPVOID lpParameter);//监听是否有新的客户端


DWORD WINAPI recvThread();//监听每个客户端


typedef struct sclient {
SOCKET socket;
char name[10];//客户端名称
char aim[10];//客户端目标
int flag;//是否创建监听线程
}sclient;


typedef struct Message {
char news[128];//消息
char aim[10];//目的用户
char name[10];//
}Message;


sclient Asclient[10];//客户端结构体


queue <Message> message;//消息队列


int flag = 0;//多少客户端
char flag2[10];
int t = 0;


int change = 0;//是否有新的客户端连接进来


SOCKET getsocket(char tem[]) {
int i;
for (i = 0; i < flag; i++) {
if (strcmp(tem, Asclient[i].name)==0) {
memset(flag2, 0, sizeof(flag2));
strcpy(flag2, Asclient[i].name);
return Asclient[i].socket;
}

}
printf("no named client---------------\n");
return 0;
}
int main()
{


//初始化套接字接口
WSADATA wsaData;
WSAStartup(0x202, &wsaData);
int i;
//创建套接字s
SOCKET s;
s = socket(AF_INET, SOCK_STREAM, 0);


//打印套接字s在创建时的信息


//定义地址结构
struct sockaddr_in serveraddr;
memset((void *)&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;


serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);// INADDR_ANY 转换过来就是0.0.0.0,表示本机的所有IP
   //serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
serveraddr.sin_port = htons(5000);


//绑定套接字
i=bind(s, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
if (i >= 0) {
printf("绑定端口成功,正在开始服务器线程..........\n");
HANDLE hListen = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)oneThread,
(LPVOID)&s, 0, NULL);
}
else {
printf("服务器初始化失败.........................\n");
}


for (i = 0; i < 1000; i++)
Sleep(100000);
//关闭套接字s
closesocket(s);
WSACleanup();


//程序中断
system("pause");


return 0;
}


DWORD WINAPI oneThread(LPVOID lpParameter) {
SOCKET s;
s = *((SOCKET *)lpParameter);
    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)acceptThread,
(LPVOID)&s, 0, NULL);
    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SendThread,
NULL, 0, NULL);
    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)recvThread,
NULL, 0, NULL);
return 0;
}
DWORD WINAPI recvThread() {
int i;
SOCKET tems;
while (1) {
if (change == 1&&flag>1) {
for (i = 0; i < flag; i++) {
if (Asclient[i].flag != 1) {
printf("开始接受信息..........3\n");
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ListenThread,
(LPVOID)&Asclient[i], 0, NULL);
Asclient[i].flag = 1;
}
}
change = 0;
}
}
return 0;
}
DWORD WINAPI acceptThread(LPVOID lpParameter) {
int i = 0;
int ret;
SOCKET ss;
SOCKET s;
SOCKET ts;
SOCKADDR_IN g_ClientAddr = { 0 };
char buf[10];
char IP[20];
s = *((SOCKET *)lpParameter);


while (1) {
  listen(s, SOMAXCONN);
  if (flag<10) {


  printf("正在监听端口\n");
  if ((ss = accept(s, NULL, NULL)) == INVALID_SOCKET) {
  continue;
  }
  else
  {
  printf("有客户端请求\n");
  memset(buf, 0, sizeof(buf));
  Asclient[i].socket = ss;


  ret = recv(ss, buf, sizeof(buf), 0);
  if (ret > 0) {
  strcpy(Asclient[i].name, buf);
  }


  memset(buf, 0, sizeof(buf));
  ret = recv(ss, buf, sizeof(buf), 0);
  if (ret > 0) {
  strcpy(Asclient[i].aim, buf);
  }
  printf("新客户端连接成功,用户名:%s     聊天目标: %s\n", Asclient[i].name, Asclient[i].aim);
  i++;
  flag++;
  change = 1;
  }


  }
  else {
  printf("当前客户端已满,请稍等再访问................\n");
  return 0;
  }
}


return 0;
}
DWORD WINAPI ListenThread(LPVOID lpParameter) {
sclient s;
Message temmessage;
char buf[128];
int ret;
s = *((sclient *)lpParameter);
strcpy(temmessage.aim, s.aim);
strcpy(temmessage.name, s.name);
while (1) {
memset(buf, 0, sizeof(buf));
ret = recv(s.socket, buf, sizeof(buf), 0);


if (ret > 0) {
strcpy(temmessage.news, buf);


message.push(temmessage);
}
else
{
t++;
printf("%d", t);
t--;
Sleep(1000);


}




}
}
DWORD WINAPI SendThread() {
SOCKET s;
Message temmessage;
char tem;
while (1) {
if (message.empty()==FALSE){
temmessage = message.front();
s = getsocket(temmessage.aim);
send(s,temmessage.name, sizeof(temmessage.name), 0);
send(s, temmessage.news, sizeof(temmessage.news), 0);
message.pop();
}
}
return 0;
}


服务器端的代码使用一个线程来监听是否有新的客户端连接,使用一个线程来接受客户端的信息,使用一个线程来转发服务器接收到的信息,看代码就很好懂了。一下是客户端代码:

//TcpClient.cpp


#include <stdio.h>


#include <winsock2.h>


#pragma comment (lib,"ws2_32.lib")
DWORD WINAPI ListenThread(LPVOID);
DWORD WINAPI SendThread(LPVOID);
char tem1[10];
int main()
{


//初始化套接字接口
WSADATA wsaData;
WSAStartup(0x202, &wsaData);
int i;
//创建套接字s
SOCKET s;
s = socket(AF_INET, SOCK_STREAM, 0);
//printf("%d\n",sizeof(s));


//指定服务器的地址结构
struct sockaddr_in serveraddr;
memset((void *)&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");
serveraddr.sin_port = htons(5000);


//发送连接请求给服务器
i=connect(s, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
if (i >= 0) {
memset(tem1, 0, sizeof(tem1));
printf("成功与服务端连接:现在开始通话----------------\n");
printf("请输入你的用户名:  ");
scanf("%s", tem1);
send(s, tem1,sizeof(tem1), 0);
memset(tem1, 0, sizeof(tem1));
printf("请输入你要聊天的人的用户名:  ");
scanf("%s", tem1);
send(s, tem1, sizeof(tem1), 0);
HANDLE hListen = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ListenThread,
(LPVOID)&s, 0, NULL);
HANDLE hListen1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SendThread,
(LPVOID)&s, 0, NULL);
}
else {
printf("连接失败\n");
}
//关闭套接字s
for (i = 0; i < 1000; i++)
Sleep(100000);
closesocket(s);


//注销套接字接口
WSACleanup();


//程序中断
system("pause");


return 0;
}
DWORD WINAPI ListenThread(LPVOID lpParameter) {
SOCKET s;
char buf[128] = { 0 };
int ret;
s = *((SOCKET *)lpParameter);
while (1) {
memset(buf, 0, sizeof(buf));
ret = recv(s, buf, sizeof(buf), 0);
if (ret > 0) {
printf("%s 说: ",buf);
}
memset(buf, 0, sizeof(buf));
ret = recv(s, buf, sizeof(buf), 0);
if (ret > 0) {
printf("%s\n", buf);
}
}
}
DWORD WINAPI SendThread(LPVOID lpParameter) {
SOCKET s;
char buf[128];
char buf1[129];
char tem;
s = *((SOCKET *)lpParameter);
while (1) {
memset(buf, 0, sizeof(buf));
scanf("%s", &buf);
send(s, buf, sizeof(buf), 0);
}
}

客户端相比之下就比较简单了,直接使用两个线程分别来接受消息以及发送消息。

有什么不足的地方请指教一下,有一个问题就是CPU的使用率会有一点高,目前可以支持10个客户端之间相互通信,你也可以自己修改相应的参数就可以了。




  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值