镜像服务器 返回连接者的ip端口回去:
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include<netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
//1.创建服务器socket
int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
//2.绑定IP地址信息
struct sockaddr_in ser_addr;
ser_addr.sin_family = AF_INET;//IPV4
ser_addr.sin_port = htons(6667) ;//采用大端序
ser_addr.sin_addr.s_addr = INADDR_ANY;//自动绑定本地网卡地址
int ret = bind(tcp_socket,(struct sockaddr *)&ser_addr, sizeof(ser_addr));
if(ret < 0)
{
perror("");
}else{
printf("绑定成功!\n");
}
//3.设置为监听模式
listen(tcp_socket,5);
//4.接收客户端链接
while (1)
{
struct sockaddr_in clien_addr;//保存对方的IP地址信息
int len = sizeof(struct sockaddr_in);
int new_socket = accept(tcp_socket, (struct sockaddr *)&clien_addr, &len);
if(new_socket > 0)
{
char *ip = inet_ntoa(clien_addr.sin_addr);
//提取端口
unsigned short port = ntohs(clien_addr.sin_port);
char bufip[1024] = {0};
sprintf(bufip , "%s:%d",ip, port);
printf("%s:%d",ip,port);
write(new_socket,bufip,strlen(bufip));
}
}
return 0;
}
利用TCP 传输协议实现 文件的传输功能
服务器接收文件代码:
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include<netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char const *argv[])
{
//1.创建服务器socket
int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
//2.绑定IP地址信息
struct sockaddr_in ser_addr;
ser_addr.sin_family = AF_INET;//IPV4
ser_addr.sin_port = htons(6667) ;//采用大端序
ser_addr.sin_addr.s_addr = INADDR_ANY;//自动绑定本地网卡地址
int ret = bind(tcp_socket,(struct sockaddr *)&ser_addr, sizeof(ser_addr));
if(ret < 0)
{
perror("");
return -1;
}else{
printf("绑定成功!\n");
}
//3.设置为监听模式
listen(tcp_socket,5);
//4.接收客户端链接
while (1)
{
printf("等待客户端发送文件\n");
int new_socket = accept(tcp_socket, NULL,NULL);
if(new_socket > 0)
{
printf("开始接收。。。\n");
//接收文件名+文件大小
char file_msg[1024];//file 文件名 文件大小
read(new_socket,file_msg,1024);
//获取文件名和文件大小
char file_name[1024];
int file_size ;
if(strstr(file_msg, "file"))
{
sscanf(file_msg, "file %s %d",file_name, &file_size);
}else{
printf("解析文件失败\n");
close(new_socket);
continue;
}
printf("对方发送的文件名:%s 文件大小%d\n",file_name,file_size);
//告诉发送端,已经得到了文件的信息
write(new_socket,"GOGOGO", strlen("GOGOGO"));
//创建文件
int fd = open("./2.jpg", O_RDWR|O_CREAT|O_TRUNC,0777);
//下载大小
int dow_size = 0;
//不断接收数据
while (1)
{
//读取网络数据
char data[4096] = {0};
int size = read(new_socket,data,4096);
dow_size += size;
//写入本地文件
write(fd,data,size);
//判断是否下载完毕
if(dow_size >= file_size)
{
printf("下载完毕\n");
//告诉发送端以及下载完毕 可以断开连接
write(new_socket, "down_ok",strlen("down_ok"));
close(fd);
close(new_socket);
break;
}else{
printf("下载进度:%d %%\n", dow_size*100/file_size);
}
}
}
}
return 0;
}
客户端发送文件代码:
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include<netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char const *argv[])
{
if(argc < 2)
{
printf("请输入发送的文件\n");
return -1;
}
//发送文件名与大小给服务器 file 文件名 文件大小
int fd = open(argv[1],O_RDWR);
if(fd < 0)
{
perror("");
return -1;
}
//1.创建服务器socket
int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
//2.设置服务器信息
struct sockaddr_in ser_addr;
ser_addr.sin_family = AF_INET;//IPV4
ser_addr.sin_port = htons(6667) ;//采用大端序
ser_addr.sin_addr.s_addr = inet_addr("192.168.202.128");//自动绑定本地网卡地址
//链接服务器
int ret = connect(tcp_socket,(struct sockaddr *)&ser_addr, sizeof(ser_addr));
if(ret < 0)
{
perror("");
return -1;
}else{
printf("链接服务器成功!\n");
}
//获取文件大小
struct stat file_size;
stat(argv[1], &file_size);
char file_msg[1024] = {0};
//拼接协议
sprintf(file_msg, "file %s %ld",argv[1], file_size.st_size);
//发送给服务器
write(tcp_socket, file_msg, strlen(file_msg));
//等待服务器应答
char rec[1024] = {0};
read(tcp_socket, rec, 1024);
printf("rec%s\n",rec);
if(strcmp(rec,"GOGOGO") == 0)
{
while (1)
{
char data[4096] = {0};
int size = read(fd, data, 4096);
if(size <= 0 )
{
printf("读取完毕\n");
break;
}
write(tcp_socket,data, size);
}
}
//等待服务器接收完毕
bzero(rec,1024);
read(tcp_socket,rec,1024);
if(strcmp(rec,"down_ok") == 0)
{
printf("关闭所有链接\n");
close(tcp_socket);
close(fd);
}
return 0;
}
结果:
利用TCP 传输协议实现 与多个客户端通信功能:并发服务器
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include<netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
struct node *head;
//设计单链表的节点
struct node
{
char data[1024];
int fd;
struct node *next;
};
//尾插入
struct node * Tail_InserNode (struct node *head , char * Dat, int fd)
{
//新建节点
struct node * Newnode = malloc(sizeof(struct node));
//指向头节点
struct node * pos = head;
while (pos->next != NULL) //为什么不写 while (pos != NULL) pos != NULL 循环结束后,pos 已经指向NULL
pos =pos ->next;
//初始化新节点
strcpy(Newnode->data,Dat);
Newnode->fd = fd;
Newnode ->next = NULL;
//插入新节点
pos->next = Newnode;
return Newnode;
}
//遍历节点
void TraverseNodes(struct node *head)
{
//1.指向链表中的第一个节点
struct node *pos = head->next;
while (pos != NULL)
{
printf("pos->data=%s\n",pos->data);
pos = pos->next;
}
printf("__________华丽的分割线_______________\n");
}
//查找节点
int FindNodes(struct node *head,char *find_data)
{
//1.遍历链表
struct node *pos = head->next;
while (pos != NULL)
{
//判断是否为需要查找的数据
if(strcmp(pos->data,find_data))
{
printf("找到数据 %s\n",pos->data);
return pos->fd;
}
pos = pos->next;
}
printf("查无此数据\n");
return -1;
}
//删除节点
void DeleteNode(struct node *head,char *del_data)
{
struct node *pos = head->next;
struct node *prev = head; //永远都指向pos的之前一个
//1.遍历链表找到需要删除的数据
while (pos != NULL)
{
if(strcmp(pos->data,del_data)) //找到需要删除的数据
{
//printf("找到删除的数据\n");
//重新连线
prev->next = pos->next;
pos->next = NULL;
free(pos); //释放节点
//回家
pos = prev;
}
prev= pos; //在pos偏移前,保存他的前一个位置
pos = pos->next; //不断偏移
}
}
//控制服务器任务
void *ctrl_task(void *arg)
{
while (1)
{
printf("1.查看在线用户 2.发送信息 3.退出服务器\n");
int n =0;
scanf("%d",&n);
if(n == 1)
{
struct people *pos=NULL;
TraverseNodes(head);
}
if(n == 2)
{
printf("请输入 IP 消息\n");
char ip[50]={0};
char msg[100]={0};
scanf("%s",ip);
scanf("%s",msg);
//找到对应的SOCKET
struct people *pos=NULL;
int socket= FindNodes(head, ip);
write(socket,msg,strlen(msg));
}
}
}
//读取任务
void *read_task(void *arg)
{
struct node *node = (struct node *)arg;
char msg[1024]={0};
while (1)
{
bzero(msg,1024);
int s=read(node->fd,msg,1024);
if(s > 0)
{
printf("IP:%s msg:%s\n",node->data,msg);
}else
{
printf("IP:%s 离线\n",node->data);
//关闭描述符
close(node->fd);
//删除节点
DeleteNode(head,node->data);
break;
}
}
pthread_exit(NULL); //退出线程
}
int main(int argc, char const *argv[])
{
//1.创建头节点
head = malloc(sizeof(struct node));
//初始化头节点
strcpy(head->data,"");
head->next = NULL;
//1.创建TCP服务器对象
int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
if(tcp_socket < 0)
{
perror("");
}else{
printf("tcp通信对象创建成功!\n");
}
//2.绑定IP地址信息
struct sockaddr_in ser_addr;
ser_addr.sin_family = AF_INET;//IPV4
ser_addr.sin_port = htons(6667) ;//采用大端序
ser_addr.sin_addr.s_addr = INADDR_ANY;//自动绑定本地网卡地址
int ret = bind(tcp_socket,(struct sockaddr *)&ser_addr, sizeof(ser_addr));
if(ret < 0)
{
perror("");
}else{
printf("绑定成功!\n");
}
//创建一个服务器控制线程
pthread_t ctrl_tid;
pthread_create(&ctrl_tid,NULL,ctrl_task,NULL);
//3.设置为监听模式
ret = listen(tcp_socket,5);
if(ret < 0)
{
perror("");
}else{
printf("监听成功!\n");
}
printf("等待客户端链接。。。\n");
//接收链接客户端
while (1)
{
struct sockaddr_in clien_addr;
socklen_t addrlen = sizeof(clien_addr);
int new_socket = accept(tcp_socket,(struct sockaddr *)&clien_addr,&addrlen);
if(new_socket<0)
{
perror("");
}else{
printf("接收链接成功:%d\n",new_socket);
}
//提取ip
char *ip = inet_ntoa(clien_addr.sin_addr);
//提取端口
unsigned short port = ntohs(clien_addr.sin_port);
printf("链接着ip:%s 端口:%d\n", ip, port);
char bufip[1024] = {0};
sprintf(bufip , "%s:%d",ip, port);
printf("%s:%d",ip,port);
struct node *new_node = Tail_InserNode(head,bufip,new_socket);
pthread_t tid;
pthread_create(&tid, NULL, read_task, new_node);
}
//关闭通信
//close(new_socket);
return 0;
}
利用TCP 传输协议实现 中转服务器
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <pthread.h>
//添加内核链表头文件
#include "list.h"
//设计在线链表
struct people
{
char ip[50]; //IP
unsigned short port; //端口
int socket; //描述符
char name[50];//名称
//添加内核链表
struct list_head list;
};
struct list_head *head=NULL;
//控制服务器任务
void *ctrl_task(void *arg)
{
while (1)
{
printf("1.查看在线用户 3.退出服务器\n");
int n =0;
scanf("%d",&n);
if(n == 1)
{
struct people *pos=NULL;
list_for_each_entry(pos,head,list) //遍历链表获取在线用户信息
{
printf("name:%s socket:%d ip:%s port:%d\n",pos->name,pos->socket,pos->ip,pos->port);
}
}
}
}
//读取任务
void *read_task(void *arg)
{
struct people *xnew = arg;
char msg[1024]={0};
while (1)
{
bzero(msg,1024);
int s=read(xnew->socket,msg,1024);
if(s > 0)
{
printf("名称:%s msg:%s\n",xnew->name,msg);
//进行转发 msg 名称 消息
if(msg[0]='m' && msg[1] == 's' && msg[2] == 'g')
{
printf("开始转发\n");
char name[50]={0};
char send_msg[100]={0};
char h[50]={0};
sscanf(msg,"%s %s %s",h,name,send_msg);
printf("name=%s\n",name);
//找到需要接收数据的socket
struct people *pos=NULL;
list_for_each_entry(pos,head,list) //遍历链表获取在线用户信息
{
if(strcmp(pos->name,name) == 0)
{
printf("转发成功\n");
write(pos->socket,send_msg,strlen(send_msg)); //转发
break;
}
}
}
}else
{
printf("IP:%s 离线\n",xnew->ip);
//关闭描述符
close(xnew->socket);
//删除节点
list_del(&xnew->list);
//释放节点
free(xnew);
break;
}
}
pthread_exit(NULL); //退出线程
}
int main()
{
//初始化内核链表
head = malloc(sizeof( struct list_head));
INIT_LIST_HEAD(head);
//1.创建服务器socket
int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
//2.绑定服务器信息
struct sockaddr_in addr;
addr.sin_family = AF_INET; //ipv4
addr.sin_port = htons(6665);//端口为 6666
addr.sin_addr.s_addr = INADDR_ANY; //本地所有网卡地址
int ret=bind(tcp_socket,(struct sockaddr *)&addr,sizeof(addr));
if(ret < 0)
{
perror("绑定失败\n");
return -1;
}
//创建一个服务器控制线程
pthread_t ctrl_tid;
pthread_create(&ctrl_tid,NULL,ctrl_task,NULL);
//3.设置为监听模式
listen(tcp_socket,5);
//接收客户端的链接请求并添加到链表中
while (1)
{
//新建节点
struct people *xnew=malloc(sizeof(struct people));
struct sockaddr_in clien_addr; //保存对方的IP地址信息
int len = sizeof(struct sockaddr);
xnew->socket = accept(tcp_socket,(struct sockaddr *)&clien_addr,&len);
if( xnew->socket > 0) //连接成功
{
printf("新的客户端链接 %d 等待注册\n",xnew->socket);
//告诉客户端需要注册设备名
write(xnew->socket,"reg_name",strlen("reg_name"));
//读取设备名
char reg_name[1024]={0};
read(xnew->socket,reg_name,1024); //超时检测
if(strstr(reg_name,"name"))
{
printf("设备注册成功\n");
//初始化其他信息
xnew->port = ntohs(clien_addr.sin_port);
strcpy(xnew->ip,inet_ntoa(clien_addr.sin_addr));
sscanf(reg_name,"name %s",xnew->name);
//插入节点
list_add_tail(&xnew->list,head);
//开启线程
pthread_t tid;
pthread_create(&tid,NULL,read_task,xnew);
pthread_detach(tid);
}else
{
close(xnew->socket);
free(xnew);
}
}
else
{
perror("");
free(xnew);
}
}
}