linux C语言TCP协议实现镜像服务器,并发服务器,文件传输
生活随笔
收集整理的這篇文章主要介紹了
linux C语言TCP协议实现镜像服务器,并发服务器,文件传输
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
鏡像服務器 返回連接者的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.創建服務器socketint tcp_socket = socket(AF_INET, SOCK_STREAM, 0);//2.綁定IP地址信息struct sockaddr_in ser_addr;ser_addr.sin_family = AF_INET;//IPV4ser_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.創建服務器socketint tcp_socket = socket(AF_INET, SOCK_STREAM, 0);//2.綁定IP地址信息struct sockaddr_in ser_addr;ser_addr.sin_family = AF_INET;//IPV4ser_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.創建服務器socketint tcp_socket = socket(AF_INET, SOCK_STREAM, 0);//2.設置服務器信息struct sockaddr_in ser_addr;ser_addr.sin_family = AF_INET;//IPV4ser_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;//IPV4ser_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);}//提取ipchar *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);//端口為 6666addr.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);}}}?
總結
以上是生活随笔為你收集整理的linux C语言TCP协议实现镜像服务器,并发服务器,文件传输的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用el-tree支持保留源节点的拖放操
- 下一篇: 六轴机械臂与单目相机的标定和视觉伺服的理