今天试着用了一下socket编程,虽然是以前基本没有接触过的领域,不过因为Unix/Linux基本哲学之一就是“一切皆文件”,一些最基本的操作倒也是很快就上手了。就和普通的文件操作一样,“open -> write/read -> close”。
socket-client是客户端程序,向服务端(socket-server)发送一些数据,服务端按照原样返回。客户端可以指定端口和服务端的IP,服务端可指定端口。例如:
$./socket-server -p 8080
$./socket-client -p 8080 -a 127.0.0.1
即指定让服务端在8080端口监听。客户端使用8080端与127.0.0.1通信。
运行效果如下:
因为都是基本的操作,所以就直接贴代码了,注释不写应该也没什么问题。
Client
// // main.cpp // socket-clinet // // Created by Ryza 14/10/31. // Copyright (c) 2014年 Ryza. All rights reserved. // #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <getopt.h> #define default_port 327 #define default_server_addr "127.0.0.1" int main(int argc, const char * argv[]) { int sockfd; ssize_t recbytes; char recv_data[4096],send_data[4096]; struct sockaddr_in server_addr; char * server_address = default_server_addr; int port = default_port; int ch; while(( ch = getopt(argc,argv,"a:p:"))!= -1) { switch(ch) { case 'a': server_address = optarg; break; case 'p': port = atoi(optarg); break; default: printf("unknown optionn"); } } memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); server_addr.sin_addr.s_addr = inet_addr(server_address); while (1) { if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) { perror("socket: "); exit(1); } if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { perror("connect: "); exit(1); } printf("\m33[1mSent: \m33[0m"); fgets(send_data, 4096, stdin); if( send(sockfd, send_data, strlen(send_data), 0) < 0) { perror("send: "); exit(1); } if(-1 == (recbytes = read(sockfd,recv_data,4096))) { perror("read: "); exit(1); } printf("\m33[1m"); recv_data[recbytes]='�'; printf("Recv: \m33[0m%s",recv_data); if (strcmp(recv_data, "Goodbye!n") == 0) { break; } close(sockfd); } return 0; }
Server
// // main.cpp // socket-server // // Created by Ryza 14/10/31. // Copyright (c) 2014年 Ryza. All rights reserved. // #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #define default_port 327 int main(int argc, const char * argv[]) { int sockfd, connfd; struct sockaddr_in server_addr; char recv_data[4096]; ssize_t recbytes; int port = default_port; int ch; while(( ch = getopt(argc,argv,"a:p:"))!= -1) { switch(ch) { case 'p': port = atoi(optarg); break; default: printf("unknown optionn"); } } if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){ perror("socket: "); exit(1); } memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(port); if( bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1){ perror("bind: "); exit(1); } if( listen(sockfd, 10) == -1){ perror("listen: "); exit(1); } printf("\m33[1mlisten on %d. ok to recv msg!n\m33[0m",port); while(1){ struct sockaddr_in client_addr; socklen_t socket_len = sizeof(struct sockaddr_in); if( (connfd = accept(sockfd, (struct sockaddr *)(&client_addr), &socket_len)) == -1){ perror("accept: "); continue; } if (fork() == 0) { recbytes = recv(connfd, recv_data, 4096, 0); recv_data[recbytes] = '�'; if (strcmp(recv_data, "closen") == 0) { write(connfd, "Goodbye!n", 32); printf("\m33[1mGoodbye %s!n\m33[0m",inet_ntoa(client_addr.sin_addr)); break; } printf("\m33[1mrecv msg from client[%s]: \m33[0m%s",inet_ntoa(client_addr.sin_addr),recv_data); write(connfd,recv_data,4096); close(connfd); exit(0); } } close(sockfd); return 0; }
博主你好,
我现在iOS设备上socket监听端口遇到了一些问题,我的app是可以保持后台运行的(播放音频),这时候其实socket还在监听,但是后台一段时间后socket就无法监听这个端口了。查了apple的文档说是后台运行要关闭监听,恢复前台再打开,否则资源有可能被系统回收,端口收到的数据将不再传递给app。请问这个有解决办法吗?(让app后台长时间运行时始终能保持监听端口)