socket编程demo(C)
server端
#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<pthread.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/time.h>
int g_connect_fd = 0;
static void * send_recv_thread(void *fd)
{
int send_len = 0, recv_len = 0;
int connect_fd;
char send_buf[128] = "send func test";
char recv_buf[64] = {0};
struct timeval r_timeout = {2, 0}, s_timeout = {2, 0}, start = {0, 0}, now = {0, 0}, diff = {0, 0};
connect_fd = g_connect_fd;
while(1)
{
retry:
if(setsockopt(connect_fd, SOL_SOCKET, SO_SNDTIMEO, (void*)&s_timeout, sizeof(struct timeval)) < 0)
{
perror("setsockopt SO_SNDTIMEO error: ");
goto end;
}
send_len = send(connect_fd, (void *)send_buf, strlen(send_buf) + 1, 0);
if(send_len < 0)
{
perror("send error: ");
if (errno == EINTR)
{
goto retry;
}
}
else if (0 == send_len)
{
perror("remote closed: ");
}
else
{
printf("send buffer: %s len = [%d]\n", send_buf, send_len);
}
recv_retry:
if(setsockopt(connect_fd, SOL_SOCKET, SO_RCVTIMEO, (void*)&r_timeout, sizeof(struct timeval)) < 0)
{
perror("setsockopt SO_RCVTIMEO error: ");
goto end;
}
recv_len = recv(connect_fd, recv_buf, 64, 0);
if(recv_len < 0)
{
perror("recv len < 0 error: ");
if(errno == EINTR)
goto recv_retry;
goto end;
}
else if(recv_len == 0)
{
perror("remote closed error: ");
goto end;
}
else
{
printf("recvie ok!\n");
}
printf("recv buf: %s len = [%d]\n", recv_buf, recv_len);
sleep(5);
}
end:
close(connect_fd);
return NULL;
}
static int server()
{
int socket_fd, connect_fd, opt = 1;
struct sockaddr_in addr;
int addr_len = sizeof(struct sockaddr_in);
char ip_addr[5];
restart:
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (socket_fd == -1)
{
perror("create socket error: ");
return -1;
}
setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
addr.sin_family = AF_INET;
addr.sin_port = htons(11022);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(socket_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
{
close(socket_fd);
perror("bind error: ");
return -1;
}
if(listen(socket_fd, 5) < 0)
{
close(socket_fd);
perror("listen error: ");
return -1;
}
while (1)
{
connect_fd = accept(socket_fd, (struct sockaddr*)&addr, (socklen_t*)&addr_len);
printf("connect_fd: %d\n", connect_fd);
if (connect_fd < 0) {
perror("accept error: ");
if(errno == EINTR) continue;
close(socket_fd);
goto restart;
}
break;
}
pthread_t sr_thread;
pthread_attr_t attr;
size_t stack_size;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &stack_size);
printf("stack size: 0x%x\n", stack_size);
pthread_attr_setstacksize(&attr, 0x80000);
pthread_attr_getstacksize(&attr, &stack_size);
printf("set stack size: 0x%x\n", stack_size);
g_connect_fd= connect_fd;
pthread_create(&sr_thread, &attr, send_recv_thread, NULL);
pthread_attr_destroy(&attr);
return 0;
}
int main(int argc, char* argv[])
{
if(server() < 0)
{
printf("error\n");
}
while (1)
{
sleep(1);
}
return 0;
}
客服端
#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<netinet/tcp.h>
#include<pthread.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<fcntl.h>
#include<sys/select.h>
#include<time.h>
#define log(fmt, arg...) \
do { \
printf("[%s: %s(): %d] " fmt "\n", __FILE__, __func__, __LINE__, ##arg); \
} while (0)
int addrinfo_test()
{
struct addrinfo *servinfo, *p;
struct addrinfo hints;
int port = 22;
int sockd;
char port_str[16] = {0};
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
sprintf(port_str, "%d", port);
printf("port_str: %s\n", port_str);
if(0 != getaddrinfo("10.192.16.50", port_str, &hints, &servinfo))
{
printf("getaddrinfo error\n");
}
for (p=servinfo; p != NULL; p = p->ai_next)
{
printf("p->ai_family: %d p->ai_socktype: %d p->ai_protocol: %d\n", p->ai_family, p->ai_socktype, p->ai_protocol);
if(p->ai_family == AF_INET)
{
printf("ipv4 addr\n");
}
else if (p->ai_family == AF_INET6)
{
printf("ipv6 addr\n");
}
else
{
printf("ai_socktype unknown : %d\n", p->ai_socktype);
}
char host_str[NI_MAXHOST];
char service_str[NI_MAXSERV];
int nameinfo_status = getnameinfo(p->ai_addr, p->ai_addrlen,
host_str, NI_MAXHOST,
service_str, NI_MAXSERV,
NI_NUMERICHOST | NI_NUMERICSERV);
if (nameinfo_status != 0) {
fprintf(stderr, "getnameinfo error: %s\n", gai_strerror(nameinfo_status));
continue;
}
printf("Host: %s, Service: %s\n", host_str, service_str);
}
return 0;
}
static int keep_sockalive(int fd)
{
const int tcp_one = 1;
const int tcp_keepidle = 45;
const int tcp_keepintvl = 30;
int ret = 0;
if (-1 == setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const void *)&tcp_one, sizeof(tcp_one)))
return -1;
if (-1 == fcntl(fd, F_SETFD, FD_CLOEXEC))
return -2;
if (-1 == setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&tcp_one, sizeof(tcp_one)))
return -3;
if (-1 == setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &tcp_one, sizeof(tcp_one)))
return -4;
if (-1 == setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &tcp_keepidle, sizeof(tcp_keepidle)))
return -5;
if (-1 == setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &tcp_keepintvl, sizeof(tcp_keepintvl)))
return -6;
return 0;
}
int connect_block(int *fd)
{
int socket_fd, flags, ret;
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_port = htons(11022);
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == socket_fd)
{
log("socket error: %s", strerror(errno));
close(socket_fd);
return -1;
}
flags = fcntl(socket_fd, F_GETFL, 0);
if (-1 == flags)
{
log("fcntl error: %s", strerror(errno));
close(socket_fd);
return -1;
}
if(-1 == fcntl(socket_fd, F_SETFL, flags & ~O_NONBLOCK))
{
log("setfl error: %s", strerror(errno));
close(socket_fd);
return -1;
}
retry:
ret = connect(socket_fd, (struct sockaddr*)&servaddr, sizeof(servaddr));
if (ret < 0)
{
if(errno == EINTR)
goto retry;
log("connect error: %s", strerror(errno));
close(socket_fd);
return -1;
}
else{
log("connect ok!\n");
}
*fd = socket_fd;
log("socket_fd: %d", socket_fd);
return ret;
}
int connect_nonblock(int* fd)
{
int socket_fd, flags, ret, error = -1;
fd_set fdsets;
socklen_t len = sizeof(error);
struct timeval c_timeout = {10, 0};
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_port = htons(11022);
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == socket_fd)
{
log("socket error: %s", strerror(errno));
return -1;
}
flags = fcntl(socket_fd, F_GETFL, 0);
if (-1 == flags)
{
log("F_GETFL errorno: %s", strerror(errno));
close(socket_fd);
return -1;
}
if(-1 == fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK))
{
log("F_SETFL error: %s", strerror(errno));
close(socket_fd);
return -1;
}
if(-1 == connect(socket_fd, (struct sockaddr*)&servaddr, sizeof(servaddr)))
{
if(errno != EINPROGRESS)
{
log("connect errno: %s", strerror(errno));
close(socket_fd);
return -1;
}
retry_1:
FD_ZERO(&fdsets);
FD_SET(socket_fd, &fdsets);
ret = select(socket_fd + 1, NULL, &fdsets, NULL, &c_timeout);
if(ret < 0 && errno == EINTR)
{
goto retry_1;
}
else if (ret > 0 && FD_ISSET(socket_fd, &fdsets))
{
ret = getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, (void *)&error, &len);
if (0 != ret || 0 != error)
{
log("getsockopt SO_ERROR eror: %s", strerror(errno));
close(socket_fd);
return -1;
}
}
else
{
log("select return error: %s", strerror(errno));
close(socket_fd);
return -1;
}
}
if (-1 == fcntl(socket_fd, F_SETFL, flags & ~O_NONBLOCK))
{
close(socket_fd);
return -1;
}
if (keep_sockalive(socket_fd) < 0)
return -1;
*fd = socket_fd;
return 0;
}
static void * client_thread_func(void * fd)
{
char recvbuf[128] = {0};
char sendBuf[128] = "send data";
int recvlen = 0;
int sendlen = 0;
int sockfd = *(int*)fd;
log("sockfd: %d", sockfd);
while (1)
{
recvlen = recv(sockfd, recvbuf, 128, 0);
if (recvlen < 0)
{
log("recv error : %s", strerror(errno));
break;
}
else if(0 == recvlen)
{
log("remote closed");
break;
}
log("recv buf : [%s] recvlen: [%d]\n", recvbuf, recvlen);
memset(recvbuf, 0, 128);
sendlen = send(sockfd, sendBuf, strlen(sendBuf)+1, 0);
if (sendlen < 0)
{
log("send error : %s", strerror(errno));
break;
}
else if(0 == sendlen)
{
log("remote closed");
break;
}
log("send buf : [%s] sendlen: [%d]\n", sendBuf, sendlen);
sleep(5);
}
free((void*)fd);
}
int test(int sel)
{
int *fd = (int*)malloc(sizeof(int));
switch (sel)
{
case 1:
if (connect_block(fd) < 0)
{
log("connect_block() FAILED!\n");
return -1;
}
else
{
log("connect_block() SUCCESS!\n");
}
break;
case 2:
if (connect_nonblock(fd) < 0)
{
log("connect_nonblock() FAILED!\n");
return -1;
}
else
{
log("connect_nonblock() SUCCESS!\n");
}
break;
default:
log("no supoort\n");
break;
}
pthread_t client_thread;
pthread_attr_t attr;
memset(&attr, 0x00, sizeof(attr));
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 0x80000);
pthread_create(&client_thread, &attr, client_thread_func, (void*)fd);
pthread_attr_destroy(&attr);
return 0;
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
printf("====================================================\n");
printf("usage:\n ");
printf("1: connect_block()\n");
printf("2: connect_nonblock()\n ");
printf("==================================================== \n");
}
int sel = (int)(argv[1][0] -'0');
test(sel);
while (1)
{
sleep(10);
}
return 0;
}
Makefile
# CC = gcc
# CV181X_GCC = riscv64-unknown-linux-musl-gcc
# CFLAGS = -Wall -Wextra
# LDFLAGS = -lpthread
# all: s1 c1
# s1: s1.c
# $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
# c1: c1.c
# $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
# clean:
# rm -f s1 c1
CC = gcc
CFLAGS = -Wall -Wextra
LDFLAGS = -lpthread
RISCV_CC = riscv64-unknown-linux-musl-gcc
RISCV_CFLAGS = -mcpu=c906fdv -march=rv64imafdcv0p7xthead -mcmodel=medany -mabi=lp64d
RISCV_LDFLAGS = -lpthread
TARGET_ARCH ?= riscv
ifeq ($(TARGET_ARCH), native)
TARGET_CC = $(CC)
TARGET_CFLAGS = $(CFLAGS)
TARGET_LDFLAGS = $(LDFLAGS)
else ifeq ($(TARGET_ARCH), riscv)
TARGET_CC = $(RISCV_CC)
TARGET_CFLAGS = $(RISCV_CFLAGS)
TARGET_LDFLAGS = $(RISCV_LDFLAGS)
else
$(error Unsupported target architecture: $(TARGET_ARCH))
endif
all: s1 c1
s1: s1.c
$(TARGET_CC) $(TARGET_CFLAGS) $< -o $@ $(TARGET_LDFLAGS)
c1: c1.c
$(TARGET_CC) $(TARGET_CFLAGS) $< -o $@ $(TARGET_LDFLAGS)
clean:
rm -f s1 c1