使用SIGALRM信號爲阻塞操作設置超時
可以處理connect和read等超市
https://blog.csdn.net/lstok2009/article/details/50100529
#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 <signal.h>
#include <unistd.h>
#include <arpa/inet.h>
#define MAXLINE 4096
typedef void (*sighandler_t)(int);
#define TIMEOUT_SET
static void connect_alarm(int sig_num)
{
//sig num is 14
printf("connect_alarm signal num:%d\n", sig_num);
return;
}
static void now_alarm(int sig_num)
{
printf("now_alarm signal num:%d\n", sig_num);
return;
}
int main(int argc, char** argv)
{
int sockfd, n;
char recvline[4096], sendline[4096];
struct sockaddr_in servaddr;
char server_ip[50] = {0};
sighandler_t p;
unsigned int remain_sec;
struct sigaction sa_alarm;
if( argc != 2){
printf("usage: ./client <ipaddress>\n");
printf("use local addr:'0.0.0.0'\n");
strcpy(server_ip, "0.0.0.0");
} else {
strcpy(server_ip, argv[1]);
}
if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
// 創建套接字描述符給sockfd
printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);
exit(0);
}
memset(&servaddr, 0, sizeof(servaddr));
//結構體清零
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(6666);//端口號
if( inet_pton(AF_INET, server_ip, &servaddr.sin_addr) <= 0){
//Linux下IP地址轉換函數,可以在將IP地址在“點分十進制”和“整數”之間轉換
printf("inet_pton error for %s\n",argv[1]);
exit(0);
}
printf("connect to server here~~~maybe wait here\n");
#ifdef TIMEOUT_SET
#if 0
p = signal(SIGALRM, connect_alarm);
if(p == SIG_ERR) {
perror("signal error");
exit(0);
}
printf("p:%p connect_alarm:%p\n", p, connect_alarm);
#else
sa_alarm.sa_flags = SA_RESETHAND;
sa_alarm.sa_handler = connect_alarm;
sigaction(SIGALRM, &sa_alarm, NULL);
#endif
remain_sec = alarm(5);
printf("remain sec:%d\n", remain_sec);
if(remain_sec != 0) {
perror("previous alarm set before");
exit(0);
}
//while(1);
#if 0
//set to null
p = signal(SIGALRM, p);
if(p == SIG_ERR) {
perror("signal error");
exit(0);
}
printf("p:%p connect_alarm:%p\n", p, connect_alarm);
#endif
#endif
if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){
//連接請求
printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
exit(-1);
}
printf("send msg to server: \n");
fgets(sendline, 4096, stdin);
if( send(sockfd, sendline, strlen(sendline), 0) < 0)
{
printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}
close(sockfd);
exit(0);
}
常規例子
server.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#define MAXLINE 4096
int main(int argc, char** argv)
{
int listenfd, connfd;
struct sockaddr_in servaddr;
char buff[4096];
int n;
if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){
printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);
exit(0);
}
memset(&servaddr, 0, sizeof(servaddr));
//協議地址
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(6666);//
//bind把一個地址族中的特定地址賦給socket
if( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1){
printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);
exit(0);
}
if( listen(listenfd, 10) == -1){
//listen 監聽
printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);
exit(0);
}
printf("======waiting for client's request======\n");
while(1){
if( (connfd = accept(listenfd, (struct sockaddr*)NULL, NULL)) == -1){
printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
continue;
}
n = recv(connfd, buff, MAXLINE, 0);
buff[n] = '\0';
printf("recv msg from client: %s\n", buff);
close(connfd);
}
close(listenfd);
}
client.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#define MAXLINE 4096
int main(int argc, char** argv)
{
int sockfd, n;
char recvline[4096], sendline[4096];
struct sockaddr_in servaddr;
if( argc != 2){
printf("usage: ./client <ipaddress>\n");
exit(0);
}
if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
// 創建套接字描述符給sockfd
printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);
exit(0);
}
memset(&servaddr, 0, sizeof(servaddr));
//結構體清零
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(6666);//端口號
if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0){
//Linux下IP地址轉換函數,可以在將IP地址在“點分十進制”和“整數”之間轉換
printf("inet_pton error for %s\n",argv[1]);
exit(0);
}
if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0){
//連接請求
printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
}
printf("send msg to server: \n");
fgets(sendline, 4096, stdin);
if( send(sockfd, sendline, strlen(sendline), 0) < 0)
{
printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
exit(0);
}
close(sockfd);
exit(0);
}