LinuxC編寫TCP,HTTP中轉SOCKET服務器(模擬)

使用LinuxC編寫TCP,HTTP多線程中轉SOCKET服務器(模擬)

數據傳輸構造:
1、物聯網節點已經將數據傳到網關。
2、網關將數據通過TCP協議傳到SOCKET中轉服務器。
3、SOCKET中轉服務器將數據通過HTTP POST傳到WEB服務器接口。

此文做的是上述2,3兩部分內容。
暫時實現了windows客戶端(模擬網關)將數據傳至Linux虛擬機服務端,Linux虛擬機服務端將數據回傳到windows用Spring boot快速搭建的一個web小接口,有待實際測驗。

/*Server*/
#include<stdio.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<netdb.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
#include<sys/wait.h>
#include<errno.h>
#include<pthread.h>

#define PORT 10086
#define MAX_CONN_LIMIT 4
#define MAXLINE 1024  



int http_post(char *ip,int port,char *page,char *buffer){  //data爲要發送的數據
    int sockfd,n;  
    char recvline[MAXLINE];  
    struct sockaddr_in servaddr;  
    char content[4096];  
    char content_line[50]; 
    sprintf(content_line,"POST /%s HTTP/1.1\r\n",page);  
    char content_host[50];  
    sprintf(content_host,"HOST: %s:%d\r\n",ip,port);  
    char content_type[] = "Content-Type: application/x-www-form-urlencoded\r\n";  
    char content_len[50];  
    char data[50];
    sprintf(data,"data=%s",buffer);
    sprintf(content_len,"Content-Length: %d\r\n\r\n",strlen(data));  
    //用sprintf函數拼接出請求行和請求頭content
    sprintf(content,"%s%s%s%s%s",content_line,content_host,content_type,content_len,data);
    if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)  
        printf("create socket(HTTP) error\n");  
    bzero(&servaddr,sizeof(servaddr));  
    servaddr.sin_family = AF_INET;  
    servaddr.sin_port = htons(8080);     //與8080端口建立連接
    if(inet_pton(AF_INET,ip,&servaddr.sin_addr) <= 0)  
        printf("inet_pton error\n");  
    if(connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) < 0)  
        printf("create connect(HTTP) error\n");  
    write(sockfd,content,strlen(content));  
    while((n = read(sockfd,recvline,MAXLINE)) > 0)   //讀取web服務器返回的值
    {  
        recvline[n] = '\n';  
        if(fputs(recvline,stdout) == EOF)  
            printf("fputs error\n");  
    }  
    if(n < 0)  
        printf("read error\n");  
    close(sockfd);

}  

static void Data_Handle(void *conn_fd);
int main(){

 int socket_fd,connect_fd;
 struct sockaddr_in servaddr;
 char buffer[4096];
 int n;
 socket_fd = socket(AF_INET,SOCK_STREAM,0);//初始化socket
 if(socket_fd == -1){
    printf("create socket error:%s(errno:%d)\n",strerror(errno),errno);
    return 0;
 }
 memset(&servaddr,0,sizeof(servaddr));
 servaddr.sin_family = AF_INET;
 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//將IP地址設置爲系統自動獲取,否則直接寫也行
 servaddr.sin_port = htons(PORT);
 int on = 1;
 setsockopt( socket_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );//設置地址複用
 if(bind(socket_fd,(struct sockaddr*)&servaddr,sizeof(servaddr))==-1){
    printf("bind socket error:%s(errno:%d)\n",strerror(errno),errno);
    return 0;
 }
 if(listen(socket_fd,MAX_CONN_LIMIT) == -1){
    printf("listen socket error:%s(errno:%d)\n",strerror(errno),errno);
    return 0;
 }

 while(1){
        printf("waiting for new connection...\n");
    connect_fd = accept(socket_fd,(struct sockaddr*)NULL,NULL);
    if(connect_fd == -1){
            printf("accept socket error:%s(errno:%d)\n",strerror(errno),errno);     
        return 0;
    }
    //加入多線程
    pthread_t thread_id;
    if(pthread_create(&thread_id,NULL,(void *)(&Data_Handle),(void *)(&connect_fd)) == -1){
       printf("create pthread error:%s(errno:%d)\n",strerror(errno),errno); 
       break;
    }
    printf("A new connection create!\n");

 }
 shutdown(socket_fd,SHUT_WR);
 printf("Server shuts down\n");
 return 0;
}

static void Data_Handle(void *conn_fd){
  int fd = *((int *)conn_fd);
  int recv_len;
  char *recv_data[MAXLINE];
  const char *msg_to_client = "Server has received your request!\n";

  while(1){
    printf("waiting for request...\n");
    memset(recv_data,0,MAXLINE);
    recv_len = read(fd,recv_data,MAXLINE);


    if(recv_len == 0){
      printf("Maybe the client has closed");
      break;
    }
    if(recv_len == -1){nm
       printf("read error:%s(errno:%d)\n",strerror(errno),errno); 
       break;
    }
    if(strcmp(recv_data,"quit")==0){
      printf("Client Quit\n");
      break;
    }
    printf("read from client : %s\n",recv_data);
    printf("data:%s\n",recv_data);
    http_post("192.168.110.1",8080,"helloWorld",recv_data);
    if(write(fd,msg_to_client,strlen(msg_to_client)) == -1){
      break; 
    }
  }
  printf("terminating current client_connection...\n");
  close(fd);
  pthread_exit(NULL);
}

最終實現效果如下
這裏寫圖片描述

參考:
http://www.cnblogs.com/nerohwang/p/3602233.html
http://blog.csdn.net/yc0188/article/details/4741871

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章