更多资料请点击:我的目录
本篇仅用于记录自己所学知识及应用,代码仍可优化,仅供参考,如果发现有错误的地方,尽管留言于我,谢谢。
要求:编写一个基于 TCP 的镜子服务器,将客户端发送过来的数据照原样反弹回去。
运行结果
/*
服务器部分:
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <pthread.h>
int tcpsock;
int newsock;
void finish()
{
write(newsock,"quit",4); //当服务器中断,给客户端发送quit
close(tcpsock);
close(newsock);
exit(0);
}
void *transfer()
{
char buf[100] = {
0}; //存放客户端发送给指定客户端的消息
while(1)
{
bzero(buf,100);
read(newsock,buf,100);
if(strstr(buf,"out") != NULL) //判断时候收到“quit”(客户端中断)
{
printf("客户端%d退出!!\n",newsock);
close(newsock);
exit(0);
}
printf("receive %s\n",buf);
write(newsock,buf,strlen(buf));
}
}
int main()
{
int ret;
struct sockaddr_in bindaddr; //定义ipv4地址结构体变量
bzero(&bindaddr,sizeof(bindaddr));
bindaddr.sin_family=AF_INET;
bindaddr.sin_addr.s_addr=inet_addr("192.168.1.157"); //绑定服务器自己的ip地址
bindaddr.sin_port=htons(10086); //绑定服务器自己的端口号
struct sockaddr_in clientaddr;
bzero(&clientaddr,sizeof(clientaddr));
int addrsize=sizeof(clientaddr);
tcpsock=socket(AF_INET,SOCK_STREAM,0); //创建tcp套接字
if(tcpsock==-1)
{
perror("创建tcp套接字!\n");
return -1;
}
int on=1;
setsockopt(tcpsock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); //设置端口释放后立即就可以被再次使用
ret=bind(tcpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr)); //绑定ip和端口号
if(ret==-1)
{
perror("绑定失败!\n");
return -1;
}
ret=listen(tcpsock,8); //监听
if(ret==-1)
{
perror("监听失败!\n");
return -1;
}
signal(SIGINT,finish);
while(1)
{
newsock=accept(tcpsock,(struct sockaddr *)&clientaddr,&addrsize);//接收客户端的连接请求
if(newsock==-1)
{
perror("接收客户端的连接请求失败!\n");
return -1;
}
printf("ip == %s\n",inet_ntoa(clientaddr.sin_addr));
printf("端口号 == %d\n",ntohs(clientaddr.sin_port));
printf("新的文件描述符:%d\n",newsock);
pthread_t id;
pthread_create(&id,NULL,&transfer,NULL);
}
}
/*
客户端部分:
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <pthread.h>
int tcpsock;
pthread_t id;
void *fun()
{
char recv[100];
while(1)
{
bzero(recv,100);
if(read(tcpsock,recv,100)) //接收服务器发送的消息
{
if(strstr(recv,"quit") != NULL) //判断时候收到“quit”(服务器中断)
{
printf("服务器出错!\n");
close(tcpsock);
exit(0);
}
printf("receive %s\n",recv);
}
}
}
void finish()
{
write(tcpsock,"out",3); //当客户端中断时,向服务器发送out
close(tcpsock);
pthread_cancel(id);
exit(0);
}
int main()
{
int ret;
char buf[100];
struct sockaddr_in bindaddr; //定义ipv4地址结构体变量
bzero(&bindaddr,sizeof(bindaddr));
bindaddr.sin_family=AF_INET;
bindaddr.sin_addr.s_addr=inet_addr("192.168.1.157"); //绑定客户端自己的ip地址
bindaddr.sin_port=htons(30000); //绑定客户端自己的端口号
struct sockaddr_in serveraddr; //定义结构体变量存放对方(服务器)的ip和端口号
bzero(&serveraddr,sizeof(serveraddr));
serveraddr.sin_family=AF_INET;
serveraddr.sin_addr.s_addr=inet_addr("192.168.1.157"); //服务器的ip地址
serveraddr.sin_port=htons(10086); //服务器的端口号
tcpsock=socket(AF_INET,SOCK_STREAM,0); //创建tcp套接字
if(tcpsock==-1)
{
perror("创建tcp套接字!\n");
return -1;
}
int on=1;
setsockopt(tcpsock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); //设置端口释放后立即就可以被再次使用
ret=bind(tcpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr)); //绑定ip和端口号
if(ret==-1)
{
perror("绑定失败!\n");
return -1;
}
ret=connect(tcpsock,(struct sockaddr *)&serveraddr,sizeof(serveraddr)); //连接服务器
if(ret==-1)
{
perror("连接服务器!\n");
return -1;
}
signal(SIGINT,finish);
pthread_create(&id,NULL,&fun,NULL);
printf("请输入要发送给服务器的信息!\n"); //发送信息给服务器
while(1)
{
bzero(buf,100);
scanf("%s",buf);
if(strstr(buf,"quit")!=NULL) //当客户端输入quit退出时,调用finish()函数
{
finish(); //向服务器发送quit
}
write(tcpsock,buf,strlen(buf));
}
close(tcpsock);
return 0;
}