同时运行客户端和服务器,一个简单的服务器可以同时接收多个客户端发来的数据...

本文详细介绍了服务器端和客户端之间的套接字通信,涉及多线程处理、字符串操作、套接字绑定、接受连接、消息传递及线程同步。通过实例展示了如何使用C++实现一个简单的TCP服务器,同时创建并管理多个并发线程来处理客户端请求。
摘要由CSDN通过智能技术生成

//————————服务器——————————

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include//fork,getpid

using namespace std;

int fd[100];//建立的套字接描诉符号。

int haha = 1;

void* thread(void* s)

{

int len = 1;

char buf[BUFSIZ];

//string a("liutengfei:");

while((len = recv(fd[haha-1],buf,BUFSIZ,0)) > 0)

{

buf[len-1] = '\0';

string c(buf,buf+len);

string b;

b += c;

printf("ID%d,%s\n",fd[haha-1],b.data());

}

return s;

}

int main()

{

int s;//服务器socket()函数返回的套字接描诉符,用于通过网络发送和接收数据

//int fd;//服务器accept()函数返回的一个信的套字结描诉符,用于与链接上的客户点进行数据的交换,原来的描诉符仍然被用于接受其他客户端的链接请求

int len;//用于recv()函数返回的字节长度

sockaddr_in my_addr;//linux提供的专用于IP地址结构体

sockaddr_in remote_addr;

socklen_t sin_size;//不能用int,必须用socklen_t,等下去查查资料

char buf[BUFSIZ];//存接收到的字节

memset(&my_addr, 0, sizeof(my_addr));//让该结构体中的全部数据为0

my_addr.sin_family = AF_INET;//地址族,定义为short类型,AF_INET表示他使用的是因特网地址族

my_addr.sin_addr.s_addr = INADDR_ANY;//INADDR_ANY表示表示任意IP地址,也可以用inet_addr("192.168.1.1")来让IP地址转换成正确的IP地址结构

my_addr.sin_port = htons(8000);//端口号,定义为short类型,后面的htons函数用于转换正确的端口号的值

if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)

{

perror("socket!");

return 1;

}

if (bind(s,(sockaddr *)&my_addr,sizeof(sockaddr)) < 0)//创建的套字接必须被绑定到一个本地IP地址和端口号用于TCP通信

{//第1个参数是套字接描诉符,第二个参数决定本地网络定义,第3个参数为sockaddr结构体的长度

perror("bind!");

return 1;//函数成果调用返回0,否则返回-1

}

listen(s,5);//开始监听客户端的连接,第一个参数是套字接描诉符,第2个参数表示表示监听队列的长度

sin_size = sizeof(sockaddr_in);//结构体的长度

while(1)

{

if((fd[haha++] = accept(s,(sockaddr *)&remote_addr,&sin_size)) < 0)//当一个链接请求被接受以后,该函数返回一个新的套字接描述符号。这个描诉符用于与远程客户通信

{//第一个参数为那个可以被监听的套字接描诉符,后面2个参数分别接受此结构的指针与长度的指针

perror("accept!");

return 1;

}

if(!fork())break;//假如成功建立子进程就跳出这该死的循环。

}

printf("accept client %s\n",inet_ntoa(remote_addr.sin_addr));//显示接受的客户端的IP

len = send(fd[haha-1],"Welcome to lthyxy's server!\n",28, 0);//发句欢迎词给客户端

string zhuji("lthyxy:");

pthread_t id;//新建立的线程的ID

int ret = pthread_create(&id,NULL,thread,NULL);//让线程进行,并进入对应的函数。

if (ret) { printf("create thread error!\n"); return 1;}//如过线程成功进行了就返回0,否则返回1?

while(1)//死循环,不停的向客户端发的信息

{

char buff[BUFSIZ];

string k1;

string k2(zhuji);

while(getline(cin,k1)){ k2 += k1;}//感觉处理没C++的方便就偷懒了一下,呵呵。

cin.clear();

len = k2.size();

strcpy(buff,k2.c_str());

buff[len] = '\n';

if(send(fd[haha-1], buff, len+1, 0) < 0)//再发回给客户端.

{

perror("write!");

return 1;

}

}

shutdown(fd[haha-1],2);

shutdown(s,2);//第一个参数套字接描诉符,后面的以后参数0表示不接受,1表示不发送,2表示既然不接受也不发送

pthread_join(id,NULL);//等待其他线程都完成运行。

return 0;

}

//————————————————客服端————————————————

#include

#include

#include

#include

#include

#include

#include

#include

#include

using namespace std;

int s;//用于套字接描诉符,为了给线程用

void* thread(void *ss)

{

int len = 1;

char buf[BUFSIZ];

//string a("lthyxy:");

while((len = recv(s,buf,BUFSIZ,0)) > 0)

{

buf[len-1] = '\0';

string c(buf,buf+len);

string b;

b += c;

printf("%s\n",b.data());

}

return ss;

}

int main()

{

int len;

sockaddr_in remote_addr;

char buf[BUFSIZ];

memset(&remote_addr, 0, sizeof(remote_addr));

remote_addr.sin_family = AF_INET;

remote_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

remote_addr.sin_port = htons(8000);

if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)

{

perror("socket!");

return 1;

}

if ((connect(s, (sockaddr *)&remote_addr, sizeof(sockaddr))) < 0)

{

perror("connect!");

return 1;

}

printf("connected to lthyxy....\n");

pthread_t id;

int ret = pthread_create(&id, NULL, thread, NULL);

if(ret)

{

printf("creat thread error!\n");

return 1;

}

string kehuname("liutengfei:");

while(1)

{

string k1(kehuname);

string k2;

while(getline(cin,k2))

{

k1 += k2;

}

cin.clear();

len = k1.size();

strcpy(buf,k1.c_str());

buf[len] = '\n';

if (send(s,buf,len+1,0) < 0)

{

perror("write!");

return 1;

}

}

shutdown(s,2);

pthread_join(id,NULL);

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值