TCP点播代码的实现
客户端1代码
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
/*
多个客户端连接同一个服务器
*/
int tcpsock;
//线程的任务函数---》专门接收服务器发送过来的信息
void *recvfromserver(void *arg)
{
char rbuf[100];
while(1)
{
bzero(rbuf,100);
recv(tcpsock,rbuf,100,0);
printf("服务器发送过来的内容是:%s\n",rbuf);
}
}
int main()
{
int ret;
char sbuf[100];
char otherip[16];
unsigned short otherport;
char cmd[500];
pthread_t id;
int n;
//定义ipv4地址体变量存放需要绑定的ip和端口号
struct sockaddr_in bindaddr;
bzero(&bindaddr,sizeof(bindaddr));
bindaddr.sin_family=AF_INET;
bindaddr.sin_addr.s_addr=htonl(INADDR_ANY); //自动匹配客户端自己的ip
bindaddr.sin_port=htons(10000); //客户端的端口号
//定义ipv4地址体变量存放女朋友(服务器)的ip和端口号
struct sockaddr_in girladdr;
bzero(&girladdr,sizeof(girladdr));
girladdr.sin_family=AF_INET;
girladdr.sin_addr.s_addr=inet_addr("192.168.22.5"); //服务器的ip
girladdr.sin_port=htons(20000); //服务器的端口号
//创建tcp套接字
tcpsock=socket(AF_INET,SOCK_STREAM,0);
if(tcpsock==-1)
{
perror("创建tcp套接字失败!\n");
return -1;
}
//取消端口绑定的限制
int on=1;
setsockopt(tcpsock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
//绑定客户端自己的ip和端口号
ret=bind(tcpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr));
if(ret==-1)
{
perror("绑定ip端口失败了!\n");
return -1;
}
//拨号连接服务器
ret=connect(tcpsock,(struct sockaddr *)&girladdr,sizeof(girladdr));
if(ret==-1)
{
perror("连接失败了!\n");
return -1;
}
//创建一个线程专门接收服务器发送过来的信息
pthread_create(&id,NULL,recvfromserver,NULL);
//循环从键盘输入内容发送给服务器
while(1)
{
bzero(sbuf,100);
bzero(otherip,16);
bzero(cmd,500);
printf("请输入你的选择,总共四种选择\n");
printf("1.发送信息给另外一个客户端,拼接格式要求:msg@对方ip@对方端口@你输入的信息!\n");
printf("2.发送表情包给另外一个客户端,拼接格式要求:emoji@对方ip@对方端口@表情包数据!\n");
printf("3.发送文件给另外一个客户端,拼接格式要求:file@对方ip@对方端口@文件内容数据!\n");
printf("4.发送信息给服务器,拼接格式要求:server@真实信息!\n");
printf("5.发送信息给其他所有的客户端,拼接格式要求:allclient@真实信息!\n");
printf("6.获取好友列表信息,拼接格式要求:clientlist@我要获取好友信息\n");
scanf("%d",&n);
switch(n)
{
case 1: //p2p(point to point)发送信息
printf("请输入对方的ip和端口号!\n");
scanf("%s",otherip);
scanf("%hu",&otherport);
printf("请输入要发送的信息内容!\n");
//依照制定的通信规则拼接得到完整的数据
scanf("%s",sbuf);
sprintf(cmd,"msg@%s@%hu@%s",otherip,otherport,sbuf);
//发送出去--》给服务器了
send(tcpsock,cmd,strlen(cmd),0);
break;
case 2: //p2p(point to point)发送表情包
break;
case 3: //p2p(point to point)发送文件
break;
case 4: //发信息给服务器
break;
}
scanf("%s",sbuf);
//发送给服务器
write(tcpsock,sbuf,strlen(sbuf));
}
//关闭套接字
close(tcpsock);
return 0;
}
客户端2代码
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
/*
多个客户端连接同一个服务器
*/
int tcpsock;
//线程的任务函数---》专门接收服务器发送过来的信息
void *recvfromserver(void *arg)
{
char rbuf[100];
while(1)
{
bzero(rbuf,100);
recv(tcpsock,rbuf,100,0);
printf("服务器发送过来的内容是:%s\n",rbuf);
}
}
int main()
{
int ret;
char sbuf[100];
char otherip[16];
unsigned short otherport;
char cmd[500];
pthread_t id;
int n;
//定义ipv4地址体变量存放需要绑定的ip和端口号
struct sockaddr_in bindaddr;
bzero(&bindaddr,sizeof(bindaddr));
bindaddr.sin_family=AF_INET;
bindaddr.sin_addr.s_addr=htonl(INADDR_ANY); //自动匹配客户端自己的ip
bindaddr.sin_port=htons(10001); //客户端的端口号
//定义ipv4地址体变量存放女朋友(服务器)的ip和端口号
struct sockaddr_in girladdr;
bzero(&girladdr,sizeof(girladdr));
girladdr.sin_family=AF_INET;
girladdr.sin_addr.s_addr=inet_addr("192.168.22.5"); //服务器的ip
girladdr.sin_port=htons(20000); //服务器的端口号
//创建tcp套接字
tcpsock=socket(AF_INET,SOCK_STREAM,0);
if(tcpsock==-1)
{
perror("创建tcp套接字失败!\n");
return -1;
}
//取消端口绑定的限制
int on=1;
setsockopt(tcpsock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
//绑定客户端自己的ip和端口号
ret=bind(tcpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr));
if(ret==-1)
{
perror("绑定ip端口失败了!\n");
return -1;
}
//拨号连接服务器
ret=connect(tcpsock,(struct sockaddr *)&girladdr,sizeof(girladdr));
if(ret==-1)
{
perror("连接失败了!\n");
return -1;
}
//创建一个线程专门接收服务器发送过来的信息
pthread_create(&id,NULL,recvfromserver,NULL);
//循环从键盘输入内容发送给服务器
while(1)
{
bzero(sbuf,100);
bzero(otherip,16);
bzero(cmd,500);
printf("请输入你的选择,总共四种选择\n");
printf("1.发送信息给另外一个客户端,拼接格式要求:msg@对方ip@对方端口@你输入的信息!\n");
printf("2.发送表情包给另外一个客户端,拼接格式要求:emoji@对方ip@对方端口@表情包数据!\n");
printf("3.发送文件给另外一个客户端,拼接格式要求:file@对方ip@对方端口@文件内容数据!\n");
printf("4.发送信息给服务器,拼接格式要求:server@真实信息!\n");
scanf("%d",&n);
switch(n)
{
case 1: //p2p(point to point)发送信息
printf("请输入对方的ip和端口号!\n");
scanf("%s",otherip);
scanf("%hu",&otherport);
printf("请输入要发送的信息内容!\n");
//依照制定的通信规则拼接得到完整的数据
scanf("%s",sbuf);
sprintf(cmd,"msg@%s@%hu@%s",otherip,otherport,sbuf);
//发送出去--》给服务器了
send(tcpsock,cmd,strlen(cmd),0);
break;
case 2: //p2p(point to point)发送表情包
break;
case 3: //p2p(point to point)发送文件
break;
case 4: //发信息给服务器
break;
}
scanf("%s",sbuf);
//发送给服务器
write(tcpsock,sbuf,strlen(sbuf));
}
//关闭套接字
close(tcpsock);
return 0;
}
客户端3代码
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
/*
多个客户端连接同一个服务器
*/
int tcpsock;
//线程的任务函数---》专门接收服务器发送过来的信息
void *recvfromserver(void *arg)
{
char rbuf[100];
while(1)
{
bzero(rbuf,100);
recv(tcpsock,rbuf,100,0);
printf("服务器发送过来的内容是:%s\n",rbuf);
}
}
int main()
{
int ret;
char sbuf[100];
char otherip[16];
unsigned short otherport;
char cmd[500];
pthread_t id;
int n;
//定义ipv4地址体变量存放需要绑定的ip和端口号
struct sockaddr_in bindaddr;
bzero(&bindaddr,sizeof(bindaddr));
bindaddr.sin_family=AF_INET;
bindaddr.sin_addr.s_addr=htonl(INADDR_ANY); //自动匹配客户端自己的ip
bindaddr.sin_port=htons(10002); //客户端的端口号
//定义ipv4地址体变量存放女朋友(服务器)的ip和端口号
struct sockaddr_in girladdr;
bzero(&girladdr,sizeof(girladdr));
girladdr.sin_family=AF_INET;
girladdr.sin_addr.s_addr=inet_addr("192.168.22.5"); //服务器的ip
girladdr.sin_port=htons(20000); //服务器的端口号
//创建tcp套接字
tcpsock=socket(AF_INET,SOCK_STREAM,0);
if(tcpsock==-1)
{
perror("创建tcp套接字失败!\n");
return -1;
}
//取消端口绑定的限制
int on=1;
setsockopt(tcpsock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
//绑定客户端自己的ip和端口号
ret=bind(tcpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr));
if(ret==-1)
{
perror("绑定ip端口失败了!\n");
return -1;
}
//拨号连接服务器
ret=connect(tcpsock,(struct sockaddr *)&girladdr,sizeof(girladdr));
if(ret==-1)
{
perror("连接失败了!\n");
return -1;
}
//创建一个线程专门接收服务器发送过来的信息
pthread_create(&id,NULL,recvfromserver,NULL);
//循环从键盘输入内容发送给服务器
while(1)
{
bzero(sbuf,100);
bzero(otherip,16);
bzero(cmd,500);
printf("请输入你的选择,总共四种选择\n");
printf("1.发送信息给另外一个客户端,拼接格式要求:msg@对方ip@对方端口@你输入的信息!\n");
printf("2.发送表情包给另外一个客户端,拼接格式要求:emoji@对方ip@对方端口@表情包数据!\n");
printf("3.发送文件给另外一个客户端,拼接格式要求:file@对方ip@对方端口@文件内容数据!\n");
printf("4.发送信息给服务器,拼接格式要求:server@真实信息!\n");
scanf("%d",&n);
switch(n)
{
case 1: //p2p(point to point)发送信息
printf("请输入对方的ip和端口号!\n");
scanf("%s",otherip);
scanf("%hu",&otherport);
printf("请输入要发送的信息内容!\n");
//依照制定的通信规则拼接得到完整的数据
scanf("%s",sbuf);
sprintf(cmd,"msg@%s@%hu@%s",otherip,otherport,sbuf);
//发送出去--》给服务器了
send(tcpsock,cmd,strlen(cmd),0);
break;
case 2: //p2p(point to point)发送表情包
break;
case 3: //p2p(point to point)发送文件
break;
case 4: //发信息给服务器
break;
}
scanf("%s",sbuf);
//发送给服务器
write(tcpsock,sbuf,strlen(sbuf));
}
//关闭套接字
close(tcpsock);
return 0;
}
服务器代码
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
/*
多个客户端连接同一个服务器
*/
//定义一个结构体表示单链表--》用来存放所有连接成功的客户端信息
struct clientlist
{
//数据域
int sock; //套接字文件描述符
char ip[16]; //存放点分十进制ip
unsigned short port; //存放端口号
//指针域
struct clientlist *next;
};
struct clientlist *myhead;
//封装函数初始化链表的头节点
struct clientlist *list_init()
{
struct clientlist *head=malloc(sizeof(struct clientlist));
head->next=NULL;
return head;
}
//封装函数把节点尾插到链表中
int mylist_add_tail(struct clientlist *newnode,struct clientlist *head)
{
//定义指针找到链表的尾部
struct clientlist *p=head;
while(p->next!=NULL)
p=p->next;
//尾插新的节点
p->next=newnode;
return 0;
}
//线程的任务函数,专门用来广播信息给所有的客户端
void *sendtoallclient(void *arg)
{
char sbuf[100];
while(1)
{
bzero(sbuf,100);
printf("请输入要广播给所有客户端的信息!\n");
scanf("%s",sbuf);
//广播给所有的客户端--》遍历链表(链表中存储了所有客户端的信息)去发送
struct clientlist *p=myhead;
while(p->next!=NULL)
{
p=p->next;
//使用当前p指向的节点中的套接字,把内容逐一发送出去
send(p->sock,sbuf,strlen(sbuf),0);
}
}
}
//线程的任务函数,专门接收各个不同客户端发送过来的信息
void *recvfromclient(void *arg)
{
char rbuf[500];
struct clientlist *temp=(struct clientlist *)arg;
while(1)
{
bzero(rbuf,500);
recv(temp->sock,rbuf,500,0);
//字符串的切割
char *p=strtok(rbuf,"@");
if(strcmp(p,"msg")==0) //说明客户端是想跟另外一个客户端点播发送信息
{
//继续切割
char *p1=strtok(NULL,"@"); //对方ip
char *p2=strtok(NULL,"@"); //对方端口号
char *p3=strtok(NULL,"@"); //真实的信息
//把字符串端口号转换成整数,方便比较
int portnum=atoi(p2);
//遍历链表找到目标客户端,然后把信息转发给这个客户端
struct clientlist *q=myhead;
while(q->next!=NULL)
{
q=q->next;
//判断当前节点是不是你要找的那个目标客户端
if(strcmp(q->ip,p1)==0 && q->port==portnum)
{
//发送给目标客户端
send(q->sock,p3,strlen(p3),0);
break;
}
}
}
if(strcmp(p,"emoji")==0) //说明客户端是想跟另外一个客户端点播发送表情包
{
}
if(strcmp(p,"file")==0) //说明客户端是想跟另外一个客户端点播发送文件
{
}
if(strcmp(p,"server")==0) //说明客户端是想跟服务器通信
{
}
if(strcmp(p,"clientlist")==0) //说明客户端是想跟服务器把所有的好友信息发给它
{
//遍历链表
//拼接ip和端口号 sprintf 张三ip@张三端口号#李四ip@李四端口号#王五ip@王五端口号
send( clientlist#拼接好的ip和端口号);
}
}
}
int main()
{
int tcpsock;
int ret;
char rbuf[100];
pthread_t id;
pthread_t otherid;
//定义ipv4地址体变量存放需要绑定的ip和端口号
struct sockaddr_in bindaddr;
bzero(&bindaddr,sizeof(bindaddr));
bindaddr.sin_family=AF_INET;
bindaddr.sin_addr.s_addr=htonl(INADDR_ANY); //自动匹配服务器的ip
bindaddr.sin_port=htons(20000); //女朋友(服务器)的端口号
//定义ipv4地址体变量存放客户端的ip和端口号
struct sockaddr_in boyaddr;
int addrsize=sizeof(boyaddr);
//初始化链表的表头
myhead=list_init();
//创建tcp套接字
tcpsock=socket(AF_INET,SOCK_STREAM,0);
if(tcpsock==-1)
{
perror("创建tcp套接字失败!\n");
return -1;
}
//取消端口绑定的限制
int on=1;
setsockopt(tcpsock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
//绑定女朋友(服务器)自己的ip和端口号
ret=bind(tcpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr));
if(ret==-1)
{
perror("绑定ip端口失败了!\n");
return -1;
}
//监听
ret=listen(tcpsock,5);
if(ret==-1)
{
perror("监听失败!\n");
return -1;
}
printf("旧的套接字(监听套接字)是:%d\n",tcpsock);
//创建一个线程专门用于服务器键盘输入内容,广播给所有的客户端
pthread_create(&id,NULL,sendtoallclient,NULL);
//循环接受不同客户端的连接请求
while(1)
{
printf("服务器的代码阻塞在accept位置了!\n");
//接收客户端的连接请求
ret=accept(tcpsock,(struct sockaddr *)&boyaddr,&addrsize);
if(ret==-1)
{
perror("接收连接请求失败了!\n");
return -1;
}
//创建一个新的节点
struct clientlist *newnode=malloc(sizeof(struct clientlist));
//初始化新的节点
newnode->sock=ret; //套接字
strcpy(newnode->ip,inet_ntoa(boyaddr.sin_addr)); //ip地址
newnode->port=ntohs(boyaddr.sin_port); //端口号
//尾插刚才的节点
mylist_add_tail(newnode,myhead);
//顺便创建一个线程专门接收这个客户端发送过来的信息
pthread_create(&otherid,NULL,recvfromclient,newnode);
}
//关闭套接字
close(tcpsock);
close(ret);
return 0;
}
TCP 广播代码实现
客户端1代码
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
/*
多个客户端连接同一个服务器
*/
int tcpsock;
//线程的任务函数---》专门接收服务器发送过来的信息
void *recvfromserver(void *arg)
{
char rbuf[100];
while(1)
{
bzero(rbuf,100);
recv(tcpsock,rbuf,100,0);
printf("服务器发送过来的内容是:%s\n",rbuf);
}
}
int main()
{
int ret;
char sbuf[100];
pthread_t id;
//定义ipv4地址体变量存放需要绑定的ip和端口号
struct sockaddr_in bindaddr;
bzero(&bindaddr,sizeof(bindaddr));
bindaddr.sin_family=AF_INET;
bindaddr.sin_addr.s_addr=htonl(INADDR_ANY); //自动匹配客户端自己的ip
bindaddr.sin_port=htons(10000); //客户端的端口号
//定义ipv4地址体变量存放女朋友(服务器)的ip和端口号
struct sockaddr_in girladdr;
bzero(&girladdr,sizeof(girladdr));
girladdr.sin_family=AF_INET;
girladdr.sin_addr.s_addr=inet_addr("192.168.22.5"); //服务器的ip
girladdr.sin_port=htons(20000); //服务器的端口号
//创建tcp套接字
tcpsock=socket(AF_INET,SOCK_STREAM,0);
if(tcpsock==-1)
{
perror("创建tcp套接字失败!\n");
return -1;
}
//取消端口绑定的限制
int on=1;
setsockopt(tcpsock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
//绑定客户端自己的ip和端口号
ret=bind(tcpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr));
if(ret==-1)
{
perror("绑定ip端口失败了!\n");
return -1;
}
//拨号连接服务器
ret=connect(tcpsock,(struct sockaddr *)&girladdr,sizeof(girladdr));
if(ret==-1)
{
perror("连接失败了!\n");
return -1;
}
//创建一个线程专门接收服务器发送过来的信息
pthread_create(&id,NULL,recvfromserver,NULL);
//循环从键盘输入内容发送给服务器
while(1)
{
bzero(sbuf,100);
printf("请输入要发送给服务器的信息!\n");
scanf("%s",sbuf);
//发送给服务器
write(tcpsock,sbuf,strlen(sbuf));
}
//关闭套接字
close(tcpsock);
return 0;
}
客户端2代码
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
/*
多个客户端连接同一个服务器
*/
int tcpsock;
//线程的任务函数---》专门接收服务器发送过来的信息
void *recvfromserver(void *arg)
{
char rbuf[100];
while(1)
{
bzero(rbuf,100);
recv(tcpsock,rbuf,100,0);
printf("服务器发送过来的内容是:%s\n",rbuf);
}
}
int main()
{
int ret;
char sbuf[100];
pthread_t id;
//定义ipv4地址体变量存放需要绑定的ip和端口号
struct sockaddr_in bindaddr;
bzero(&bindaddr,sizeof(bindaddr));
bindaddr.sin_family=AF_INET;
bindaddr.sin_addr.s_addr=htonl(INADDR_ANY); //自动匹配客户端自己的ip
bindaddr.sin_port=htons(10001); //客户端的端口号
//定义ipv4地址体变量存放女朋友(服务器)的ip和端口号
struct sockaddr_in girladdr;
bzero(&girladdr,sizeof(girladdr));
girladdr.sin_family=AF_INET;
girladdr.sin_addr.s_addr=inet_addr("192.168.22.5"); //服务器的ip
girladdr.sin_port=htons(20000); //服务器的端口号
//创建tcp套接字
tcpsock=socket(AF_INET,SOCK_STREAM,0);
if(tcpsock==-1)
{
perror("创建tcp套接字失败!\n");
return -1;
}
//取消端口绑定的限制
int on=1;
setsockopt(tcpsock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
//绑定客户端自己的ip和端口号
ret=bind(tcpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr));
if(ret==-1)
{
perror("绑定ip端口失败了!\n");
return -1;
}
//拨号连接服务器
ret=connect(tcpsock,(struct sockaddr *)&girladdr,sizeof(girladdr));
if(ret==-1)
{
perror("连接失败了!\n");
return -1;
}
//创建一个线程专门接收服务器发送过来的信息
pthread_create(&id,NULL,recvfromserver,NULL);
//循环从键盘输入内容发送给服务器
while(1)
{
bzero(sbuf,100);
printf("请输入要发送给服务器的信息!\n");
scanf("%s",sbuf);
//发送给服务器
write(tcpsock,sbuf,strlen(sbuf));
}
//关闭套接字
close(tcpsock);
return 0;
}
客户端3代码
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
/*
多个客户端连接同一个服务器
*/
int tcpsock;
//线程的任务函数---》专门接收服务器发送过来的信息
void *recvfromserver(void *arg)
{
char rbuf[100];
while(1)
{
bzero(rbuf,100);
recv(tcpsock,rbuf,100,0);
printf("服务器发送过来的内容是:%s\n",rbuf);
}
}
int main()
{
int ret;
char sbuf[100];
pthread_t id;
//定义ipv4地址体变量存放需要绑定的ip和端口号
struct sockaddr_in bindaddr;
bzero(&bindaddr,sizeof(bindaddr));
bindaddr.sin_family=AF_INET;
bindaddr.sin_addr.s_addr=htonl(INADDR_ANY); //自动匹配客户端自己的ip
bindaddr.sin_port=htons(10002); //客户端的端口号
//定义ipv4地址体变量存放女朋友(服务器)的ip和端口号
struct sockaddr_in girladdr;
bzero(&girladdr,sizeof(girladdr));
girladdr.sin_family=AF_INET;
girladdr.sin_addr.s_addr=inet_addr("192.168.22.5"); //服务器的ip
girladdr.sin_port=htons(20000); //服务器的端口号
//创建tcp套接字
tcpsock=socket(AF_INET,SOCK_STREAM,0);
if(tcpsock==-1)
{
perror("创建tcp套接字失败!\n");
return -1;
}
//取消端口绑定的限制
int on=1;
setsockopt(tcpsock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
//绑定客户端自己的ip和端口号
ret=bind(tcpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr));
if(ret==-1)
{
perror("绑定ip端口失败了!\n");
return -1;
}
//拨号连接服务器
ret=connect(tcpsock,(struct sockaddr *)&girladdr,sizeof(girladdr));
if(ret==-1)
{
perror("连接失败了!\n");
return -1;
}
//创建一个线程专门接收服务器发送过来的信息
pthread_create(&id,NULL,recvfromserver,NULL);
//循环从键盘输入内容发送给服务器
while(1)
{
bzero(sbuf,100);
printf("请输入要发送给服务器的信息!\n");
scanf("%s",sbuf);
//发送给服务器
write(tcpsock,sbuf,strlen(sbuf));
}
//关闭套接字
close(tcpsock);
return 0;
}
服务器代码实现
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
/*
多个客户端连接同一个服务器
*/
//定义一个结构体表示单链表--》用来存放所有连接成功的客户端信息
struct clientlist
{
//数据域
int sock; //套接字文件描述符
char ip[16]; //存放点分十进制ip
unsigned short port; //存放端口号
//指针域
struct clientlist *next;
};
struct clientlist *myhead;
//封装函数初始化链表的头节点
struct clientlist *list_init()
{
struct clientlist *head=malloc(sizeof(struct clientlist));
head->next=NULL;
return head;
}
//封装函数把节点尾插到链表中
int mylist_add_tail(struct clientlist *newnode,struct clientlist *head)
{
//定义指针找到链表的尾部
struct clientlist *p=head;
while(p->next!=NULL)
p=p->next;
//尾插新的节点
p->next=newnode;
return 0;
}
//线程的任务函数,专门用来广播信息给所有的客户端
void *sendtoallclient(void *arg)
{
char sbuf[100];
while(1)
{
bzero(sbuf,100);
printf("请输入要广播给所有客户端的信息!\n");
scanf("%s",sbuf);
//广播给所有的客户端--》遍历链表(链表中存储了所有客户端的信息)去发送
struct clientlist *p=myhead;
while(p->next!=NULL)
{
p=p->next;
//使用当前p指向的节点中的套接字,把内容逐一发送出去
send(p->sock,sbuf,strlen(sbuf),0);
}
}
}
//线程的任务函数,专门接收各个不同客户端发送过来的信息
void *recvfromclient(void *arg)
{
char rbuf[100];
struct clientlist *temp=(struct clientlist *)arg;
while(1)
{
bzero(rbuf,100);
recv(temp->sock,rbuf,100,0);
printf("有个客户端,ip:%s 端口:%hu 发送信息给我了,信息是:%s\n",temp->ip,temp->port,rbuf);
}
}
int main()
{
int tcpsock;
int ret;
char rbuf[100];
pthread_t id;
pthread_t otherid;
//定义ipv4地址体变量存放需要绑定的ip和端口号
struct sockaddr_in bindaddr;
bzero(&bindaddr,sizeof(bindaddr));
bindaddr.sin_family=AF_INET;
bindaddr.sin_addr.s_addr=htonl(INADDR_ANY); //自动匹配服务器的ip
bindaddr.sin_port=htons(20000); //女朋友(服务器)的端口号
//定义ipv4地址体变量存放客户端的ip和端口号
struct sockaddr_in boyaddr;
int addrsize=sizeof(boyaddr);
//初始化链表的表头
myhead=list_init();
//创建tcp套接字
tcpsock=socket(AF_INET,SOCK_STREAM,0);
if(tcpsock==-1)
{
perror("创建tcp套接字失败!\n");
return -1;
}
//取消端口绑定的限制
int on=1;
setsockopt(tcpsock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
//绑定女朋友(服务器)自己的ip和端口号
ret=bind(tcpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr));
if(ret==-1)
{
perror("绑定ip端口失败了!\n");
return -1;
}
//监听
ret=listen(tcpsock,5);
if(ret==-1)
{
perror("监听失败!\n");
return -1;
}
printf("旧的套接字(监听套接字)是:%d\n",tcpsock);
//创建一个线程专门用于服务器键盘输入内容,广播给所有的客户端
pthread_create(&id,NULL,sendtoallclient,NULL);
//循环接受不同客户端的连接请求
while(1)
{
printf("服务器的代码阻塞在accept位置了!\n");
//接收客户端的连接请求
ret=accept(tcpsock,(struct sockaddr *)&boyaddr,&addrsize);
if(ret==-1)
{
perror("接收连接请求失败了!\n");
return -1;
}
//创建一个新的节点
struct clientlist *newnode=malloc(sizeof(struct clientlist));
//初始化新的节点
newnode->sock=ret; //套接字
strcpy(newnode->ip,inet_ntoa(boyaddr.sin_addr)); //ip地址
newnode->port=ntohs(boyaddr.sin_port); //端口号
//尾插刚才的节点
mylist_add_tail(newnode,myhead);
//顺便创建一个线程专门接收这个客户端发送过来的信息
pthread_create(&otherid,NULL,recvfromclient,newnode);
}
//关闭套接字
close(tcpsock);
close(ret);
return 0;
}