有时候我们调试两个不同内网的设备时,网络通信是一件比较麻烦的事。而且现在许多地方的宽带拨号获取的已然是服务商提供的大内网IP段了。
我们知道,不同内网间是不通的,虽然可以在两个网络内通过端口映射来实现,但实现难度较大,并且不一定拥有主路由的控制权限。
为此,依据对socket的学习,特意写了一个基于外网服务器转发的两客户端通信程序,将该代码编译后在服务器上执行即可,要通信的两个设备都以客户端的形式连接到服务器,客户端便能实现通信。
/* C socket server example */ #include<stdio.h> #include<string.h> #include <sys/types.h> #include<sys/socket.h> #include<arpa/inet.h> #include<unistd.h> #include <pthread.h> #define BUFSIZE 2000 void* client1fun(void*); int socket_desc, client_sock1, client_sock2, c1, c2, read_size; struct sockaddr_in server, client1,client2; char client_message[BUFSIZE]; int clientn; int main(int argc, char *argv[]) { clientn = 0; int portno = atoi(argv[1]); pthread_t sender, client1, client2; pthread_create(&client1, NULL, client1fun, NULL); //Create socket socket_desc = socket(AF_INET, SOCK_STREAM, 0); if (socket_desc == -1) { printf("Could not create socket"); } puts("Socket created"); //Prepare the sockaddr_in structure server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons((unsigned short)portno); //Bind if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) { //print the error message perror("bind failed. Error"); return 1; } puts("bind done"); //Listen listen(socket_desc, 2); //Accept and incoming connection puts("Waiting for incoming connections..."); while (1) { int n; char buf[BUFSIZE]; bzero(buf, BUFSIZE); printf("client2:\n"); //accept connection from an incoming client client_sock2 = accept(socket_desc, (struct sockaddr *)&client2, (socklen_t*)&c2); if (client_sock2 < 0) { perror("accept failed"); exit(1); } clientn++; puts("Connection accepted"); //write(client_sock2, "Welecom!\n", strlen("Welecom!\n")); while (1) { n = read(client_sock2, buf, BUFSIZE); if (n < 0) { perror("recv failed"); exit(1); } if (n == 0) { clientn--; break; } printf("%s", buf); if (clientn < 2) { //write(client_sock2, "No respond!\n", strlen("No respond!\n")); } if (clientn == 2) { write(client_sock1, buf, strlen(buf)); } } close(client_sock2); } pthread_join(client1, NULL); return 0; } void* client1fun(void* client_sock) { while (1) { int n; char buf[BUFSIZE]; bzero(buf, BUFSIZE); sleep(1); printf("client1"); //accept connection from an incoming client client_sock1 = accept(socket_desc, (struct sockaddr *)&client1, (socklen_t*)&c1); if (client_sock1 < 0) { perror("accept failed"); exit(1); } clientn++; puts("Connection accepted"); //write(client_sock1, "Welecom!\n", strlen("Welecom!\n")); while (1) { n = read(client_sock1, buf, BUFSIZE); if (n < 0) { perror("recv failed"); exit(1); } if (n == 0) { clientn--; break; } printf("%s", buf); if (clientn < 2) { //write(client_sock1, "No respond!\n", strlen("No respond!\n")); } if (clientn == 2) { write(client_sock2, buf, strlen(buf)); } } close(client_sock1); } }
注意:编译请加参数 -pthread 。
上个版本存在许多问题,现在修正部分BUG并增加用户友好性,代码如下:
/* C socket server example */ #include<stdio.h> #include<string.h> #include <sys/types.h> #include<sys/socket.h> #include<arpa/inet.h> #include<unistd.h> #include <pthread.h> #define BUFSIZE 2000 void* client1fun(void*); int socket_desc, client_sock1, client_sock2, c1, c2; struct sockaddr_in server, client, client2; int clientn; int main(int argc, char *argv[]) { clientn = 0; int portno = atoi(argv[1]); pthread_t sender, client1; pthread_create(&client1, NULL, client1fun, NULL); //Create socket socket_desc = socket(AF_INET, SOCK_STREAM, 0); if (socket_desc == -1) { printf("Could not create socket"); } puts("Socket created"); //Prepare the sockaddr_in structure server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(portno); //Bind if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) { //print the error message perror("bind failed. Error"); return 1; } puts("bind done"); //Listen listen(socket_desc, 2); //Accept and incoming connection puts("Waiting for incoming connections..."); while (1) { int n; char buf[BUFSIZE]; bzero(buf, BUFSIZE); int ss = sizeof(client2); //accept connection from an incoming client client_sock2 = accept(socket_desc, (struct sockaddr *)&client2, (socklen_t*)&ss); if (client_sock2 < 0) { perror("accept failed"); exit(1); } clientn++; printf("Connection accepted fron %s:%d\n", inet_ntoa(client2.sin_addr), client2.sin_port); //write(client_sock2, "Welecom!\n", strlen("Welecom!\n")); while (n = read(client_sock2, buf, BUFSIZE)) { printf("[%s:%d]: %s\n", inet_ntoa(client2.sin_addr), client2.sin_port, buf); if (clientn == 2) { write(client_sock1, buf, strlen(buf)); } } clientn--; printf("Client [%s:%d] ofline\n",inet_ntoa(client2.sin_addr), client2.sin_port); close(client_sock2); } pthread_join(client1, NULL); return 0; } void* client1fun(void* client_sock) { while (1) { int n; char buf[BUFSIZE]; bzero(buf, BUFSIZE); sleep(1); int ss = sizeof(client); //accept connection from an incoming client client_sock1 = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&ss); if (client_sock1 < 0) { perror("accept failed"); exit(1); } clientn++; printf("Connection accepted fron %s:%d\n", inet_ntoa(client.sin_addr), client.sin_port); //write(client_sock1, "Welecom,1!\n", strlen("Welecom!\n")); while (n = read(client_sock1, buf, BUFSIZE)) { //n = read(client_sock1, buf, BUFSIZE); printf("[%s:%d]: %s\n", inet_ntoa(client.sin_addr), client.sin_port, buf); if (clientn == 2) { write(client_sock2, buf, strlen(buf)); } } clientn--; printf("Client [%s:%d] ofline\n", inet_ntoa(client.sin_addr), client.sin_port); close(client_sock1); } }