Linux下socket有select、poll、epoll和AIO等方式,其中,前三种为同步方式。
有很多种方法可以设置socket为非阻塞模式,常用的是使用fcntl(sockfd, F_SETFL, O_NONBLOCK);
在阻塞模式下,可以通过setsockopt来设置(读/写)超时,connect也可以用setsockopt来设置,与写参数一致:
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO,&timeo, len);
connect的超时一般是nonblocking+select。
参考
Linux IO模式及 select、poll、epoll详解
TCP服务端
创建socket -> bind -> listen -> accept -> send/recv -> close
代码摘自http://blog.csdn.net/shallnet/article/details/17734919,后同
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "server.h"
#include "ly_debug.h"
void accept_handle(int connfd, struct sockaddr_in peeraddr);
int main(int argc, const char *argv[])
{
int sockfd, connfd;
struct sockaddr_in seraddr, peeraddr;
socklen_t addrlen;
COMPILE_TIME_PRINT;
if (argc != 2) {
printf("Usage: %s <port>\n", argv[0]);
return -1;
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
LY_ERR("socket: %s\n", strerror(errno));
return -1;
}
seraddr.sin_family = AF_INET;
seraddr.sin_port = ntohs(atoi(argv[1]));
seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sockfd, (struct sockaddr *)&seraddr, sizeof(struct sockaddr))) {
LY_ERR("bind: %s\n", strerror(errno));
return -1;
}
if (listen(sockfd, MAX_CONN) < 0) {
LY_ERR("listen: %s\n", strerror(errno));
return -1;
}
addrlen = sizeof(struct sockaddr);
for (;;) {
connfd = accept(sockfd, (struct sockaddr *)(&peeraddr), &addrlen);
if (connfd < 0) {
LY_ERR("accept: %s\n", strerror(errno));
continue;
}
accept_handle(connfd, peeraddr);
}
return 0;
}
void accept_handle(int connfd, struct sockaddr_in peeraddr)
{
char buf[32] = "Hello, welcome to server!";
LY_IFO("Receive request from %s, port %d\n",
inet_ntop(AF_INET, &peeraddr.sin_addr, buf, sizeof(buf)),
ntohs(peeraddr.sin_port));
//sleep(10);
if (send(connfd, buf, sizeof(buf), 0) < 0) {
LY_ERR("send: %s\n", strerror(errno));
return;
}
close(connfd);
LY_IFO("send info: %s\n", buf);
}
TCP客户端
创建socket -> connect -> send/recv->close
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "ly_debug.h"
int main(int argc, const char *argv[])
{
int sockfd;
struct sockaddr_in seraddr;
char recvbuf[32];
COMPILE_TIME_PRINT;
if (argc != 3) {
LY_PRT("Usage: %s <ip> <port>\n", argv[0]);
return -1;
}
if (inet_pton(AF_INET, argv[1], &seraddr.sin_addr) < 0) {
LY_ERR("inet_pton: %s\n", strerror(errno));
return -1;
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
LY_ERR("socket: %s\n", strerror(errno));
return -1;
}
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons(atoi(argv[2]));
if (connect(sockfd, (struct sockaddr *)(&seraddr),
sizeof(struct sockaddr)) < 0) {
LY_ERR("connect: %s\n", strerror(errno));
return -1;
}
if (recv(sockfd, recvbuf, sizeof(recvbuf), 0) < 0) {
LY_ERR("recv: %s\n", strerror(errno));
return -1;
}
LY_PRT("From server: %s\n", recvbuf);
close(sockfd);
return 0;
}
来源:oschina
链接:https://my.oschina.net/u/2281329/blog/735492