功能:
1.实现客户端与客户端之间的TCP双向通信;
2.服务器记录客户端实名连接,并显示客户端数据记录;
3.客户端退出,服务器和另一客户端显示相应提示;
服务器代码思路:
1.定义数组保存客户端文件描述符;
2.主程序负责接收客户端1的数据发送给客户端2;
3.开展一个线程负责接收到客户端2的信息发送给客户端1;
客户端代码思路:
1.建立socket连接
2.绑定IP和端口号
3.主动连接服务器
4.植入线程--TCP接收数据
5.TCP发送数据
服务器代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
//定义客户端结构体
struct sockaddr_in client;
int sockfd;
int arr_fd[2]; //客户端文件描述符
char arr_ip[2][20]; //客户端IP数组
//TCP接收客户端2数据发送客户端1
void *show(void *arg){
char buf[50];
char buff[30] = "对方客户端已关闭!\n";
while(1){
bzero(buf,sizeof(buf));
int ret = recv(arr_fd[1],buf,sizeof(buf),0);
if(ret == 0 || ret < 0)//接收方向是客户端2的arr_fd
{
sleep(1);
close(sockfd);
send(arr_fd[0],buff,sizeof(buff),0);
printf("客户端 %s 已关闭\n", arr_ip[1]);
break;
}else if(ret < 0 || errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN){
continue;
}
send(arr_fd[0],buf,sizeof(buf),0);//向客户端1的arr_fd发送数据
printf("客户端%s:%s\n",arr_ip[1],buf);
}
}
int main(void)
{
//建立socket连接
sockfd=socket(AF_INET,SOCK_STREAM,0);//IPV4 TCP 0:前两个参生效
if(sockfd<0){
perror("socket");
return -1;
}
printf("sockfd:%d\n",sockfd);
//声明服务器结构体
struct sockaddr_in server;
server.sin_family=AF_INET;//地址族 代表选择IPv4
server.sin_port=htons(10086);//端口号 //因为有大小端序之分,所以要转换端序
server.sin_addr.s_addr=inet_addr("192.168.90.116");//IP地址 点分十进制转化网络二进制
//绑定IP和端口号
if(bind(sockfd,(struct sockaddr *)&server,sizeof(server))){
perror("bind");
return -1;
}
//监听
listen(sockfd,8);
//等待客户端连接
int len = sizeof(client), i = 0;
for(int i = 0; i < 2; i++){
arr_fd[i] = accept(sockfd,(struct sockaddr *)&client,&len);
if(arr_fd[i] < 0){
perror("accept");
return -1;
}
printf("客户%d上线\n",arr_fd[i]);
strcpy(arr_ip[i],inet_ntoa(client.sin_addr));
printf("其IP:%s PORT:%d\n",arr_ip[i],ntohs(client.sin_port));
}
//植入线程
pthread_t tid2;
pthread_create(&tid2,NULL,show,NULL);
pthread_detach(tid2);//线程收尸
//TCP接收客户端1数据发送客户端2
char buf[50];
char buff[30] = "对方客户端已关闭!\n";
while(1){
bzero(buf,sizeof(buf));
int ret = recv(arr_fd[0],buf,sizeof(buf),0);
if(ret == 0)//接收方向是客户端1的arr_fd
{
sleep(1);
close(sockfd);
send(arr_fd[1], buff, sizeof(buff), 0);
printf("客户端 %s 已关闭\n", arr_ip[0]);
break;
}else if(ret < 0 || errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN){
continue;
}
send(arr_fd[1],buf,sizeof(buf),0);//向客户端2的arr_fd发送数据
printf("客户端%s:%s\n",arr_ip[0],buf);
}
return 0;
}
客户端代码:
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
//实现双向通信 ---线程
int fd;
void *show(void *arg){
//接收
int sockfd = *(int *)arg;
char buf[50];
while(1){
bzero(buf, sizeof(buf));
recv(sockfd,buf,sizeof(buf),0);
printf("服务器: %s \n",buf);
}
}
int main(void)
{
//1.建立socket连接
int sockfd = socket(AF_INET, SOCK_STREAM, 0);//IPv4
if(sockfd < 0){
perror("socket");
return -1;
}
printf("sockfd = %d\n", sockfd);
//2.绑定IP和端口号
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(10086);
server.sin_addr.s_addr = inet_addr("192.168.90.116");
//3.主动连接
if(connect(sockfd, (struct sockaddr *)&server, sizeof(server))){
perror("socket");
return -1;
}
//植入线程
pthread_t tid;
pthread_create(&tid, NULL, show, &sockfd);
//5.TCP发送
char buf[50];
while(1){
bzero(buf, sizeof(buf));
scanf("%s", buf);
send(sockfd,buf,sizeof(buf),0);
}
return 0;
}
运行结果:
文章来源:https://www.toymoban.com/news/detail-614740.html
文章来源地址https://www.toymoban.com/news/detail-614740.html
到了这里,关于TCP通信—客户端与客户端的双向通信的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!