Невозможно запустить TCP-сервер на iOS, сотовая связь
Я пытаюсь запустить TCP-сервер на iOS от сотовой связи. Для того чтобы задать этот вопрос, я написал эту очень упрощенную версию сервера и клиента на C, используя socket/bind/listen/accept/etc. Это прекрасно работает, когда я запускаю серверную программу с сервера. Когда я запускаю серверную программу из приложения iOS через Cellular (без Wi-Fi), клиент никогда не подключается к серверу. Вот мой код:
Сервер:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <pthread.h>
#include "tcp_server_IPv4.h"
#define SZ_SOCKADDR_IN sizeof(struct sockaddr_in)
void pfail(char *w) {
printf("pfail %s\n", w);
perror(w);
exit(1);
}
void *tcp_server_IPv4_thread_routine(void *arg) {
int tcp4_sockfd = 0, tcp4_new_fd = 0;
char wes[64];
tcp4_sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in their_addr = {0};
struct sockaddr_in serv_addr = {0};
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(0);
int br = bind(tcp4_sockfd, (struct sockaddr*)&serv_addr, SZ_SOCKADDR_IN);
if (br == -1) {
pfail("PROBLEM BINDING");
}
int lr = listen(tcp4_sockfd, 5);
if (lr == -1) {
pfail("PROBLEM LISTENING");
}
socklen_t gsn_len = sizeof(serv_addr);
int gsn = getsockname(tcp4_sockfd, (struct sockaddr*)&serv_addr, &gsn_len);
if (gsn == -1) pfail("getsockname");
inet_ntop(AF_INET, &serv_addr, wes, sizeof(wes));
printf("start listening on (%s) port (%d)...", wes, ntohs(serv_addr.sin_port));
int tcp_running = 1;
while (tcp_running) { // main accept() loop
socklen_t sin_size = sizeof their_addr;
tcp4_new_fd = accept(tcp4_sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (tcp4_new_fd == -1) {
perror("accept");
continue;
}
inet_ntop(their_addr.sin_family, &their_addr.sin_addr, wes, sizeof wes);
printf("server: got connection from %s\n", wes);
if (!fork()) { // this is the child process
close(tcp4_sockfd); // child doesn't need the listener
if (send(tcp4_new_fd, "Hello, world!", 13, 0) == -1)
perror("send");
close(tcp4_new_fd);
exit(0);
}
close(tcp4_new_fd); // parent doesn't need this
}
pthread_exit("exiting fire_up_tcp thread normally");
}
void start_tcp_server_IPv4() {
pthread_t tcpt4;
char *w4 = "TCP server IPv4 thread";
int pr4 = pthread_create(&tcpt4, NULL, tcp_server_IPv4_thread_routine, (void *)w4);
if (pr4) pfail("create thread for fire_up_tcp_server_v4");
}
Клиент:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define PORT_NUMBER 57020
#define SERVER_ADDRESS "70.208.71.248"
#define MAXDATASIZE 200 // max number of bytes we can get at once
int main(int argc, char *argv[]) {
int sockfd, numbytes;
char buf[MAXDATASIZE];
char ip_str[INET6_ADDRSTRLEN];
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("client: socket");
exit(1);
}
struct sockaddr_in sa_server = {0};
sa_server.sin_family = AF_INET;
inet_pton(AF_INET, SERVER_ADDRESS, &(sa_server.sin_addr));
sa_server.sin_port = htons(PORT_NUMBER);
inet_ntop(AF_INET, &sa_server.sin_addr, ip_str, sizeof ip_str);
printf("Try connecting to (%s)(%d)\n", ip_str, ntohs(sa_server.sin_port));
if (connect(sockfd, (struct sockaddr *)&sa_server, sizeof(struct sockaddr_in)) == -1) {
fprintf(stderr, "Error on connect --> %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
puts("CLIENT::Connection successful.");
char fr[128];
sprintf(fr, "Some text here to send");
if (send(sockfd, fr, sizeof fr, 0) < 0) {
fprintf(stderr, "Error on send --> %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
perror("recv");
exit(1);
}
buf[numbytes] = '\0';
printf("client: received '%s'\n",buf);
close(sockfd);
return 0;
}
Результаты запуска getifaddrs() на устройстве iOS. Все адреса pdp_ip работают и работают:
(interface)(family)(ip)
(lo0)(2)(127.0.0.1)
(lo0)(30)(::1)
(lo0)(30)
(pdp_ip0)(2)(100.114.61.107)
(pdp_ip0)(30)(fe80::4d5:31ee:ba73:d63a)
(pdp_ip0)(30)(2600:1001:b101:600d:1076:2a12:b461:2a02)
(pdp_ip0)(30)(2600:1001:b101:600d:89e3:c982:c32a:b6b2)
(pdp_ip2)(30)(fe80::18b6:a5a7:33a2:13f6)
(pdp_ip2)(30)(2600:1001:812f:cec5:49:69a:d1b9:cc47)
(pdp_ip2)(30)(2600:1001:812f:cec5:e936:25c5:702:e067)
(pdp_ip2)(30)(2600:1001:812f:cec5:48de:1765:5cb5:d56c)
(en2)(30)(fe80::10d5:2496:594f:ff72)
(en2)(2)(169.254.249.210)
(ipsec1)(30)(fe80::26f0:94ff:fe9a:50bc)
(utun0)(30)(fe80::99a1:9bf7:428e:8166)
(utun1)(30)(fe80::4b1d:be95:bbf2:bf02)
(utun2)(30)(fe80::1748:1a1a:c5ee:bda9)
(utun3)(30)(fe80::d3c1:79bc:7613:ffb)
(utun4)(30)(fe80::d3c8:e837:ba74:67dc)