23,125
社区成员
发帖
与我相关
我的任务
分享
//#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <errno.h>
#include <arpa/inet.h>
#ifndef _SOCKET_H
#define _SOCKET_H
const static int TIMEOUT = 5; /* second */
#define unlikely(x) (x)
static int connect_to(char *ip, unsigned int port)
{
int fd, ret, value = 1;
struct sockaddr_in addr;
struct linger linger_opt = {1, 0};
struct timeval timeout_opt = {TIMEOUT, 0};
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if (inet_pton(AF_INET, ip, &addr.sin_addr) != 1) {
ret = -1;
goto err;
}
fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fd < 0) {
ret = -1;
goto err;
}
ret = setsockopt(fd, SOL_SOCKET, SO_LINGER, &linger_opt,
sizeof(linger_opt));
if (ret < 0)
goto err_close;
ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value));
if (ret < 0)
goto err_close;
ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout_opt,
sizeof(timeout_opt));
if (ret < 0)
goto err_close;
ret = setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout_opt,
sizeof(timeout_opt));
if (ret < 0)
goto err_close;
ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
if (ret < 0)
goto err_close;
return fd;
err_close:
close(fd);
err:
fprintf(stderr, "Failed errno:%d(%m)\n", errno);
return ret;
}
static int64_t net_read(int fd, void *buf, int64_t count)
{
char *p = buf;
int64_t sum = 0;
while(count > 0) {
int64_t loaded = 0;
while(1) {
loaded = read(fd, p, count);
if (unlikely(loaded < 0) && (errno == EINTR))
continue;
break;
}
if (unlikely(loaded < 0))
return -1;
if (unlikely(loaded == 0))
return sum;
count -= loaded;
p += loaded;
sum += loaded;
}
return sum;
}
static int64_t net_write(int fd, void *buf, int64_t count)
{
char *p = buf;
int64_t sum = 0;
while (count > 0) {
int64_t written = 0;
while (1) {
written = write(fd, p, count);
if (unlikely(written < 0) && (errno == EINTR))
continue;
break;
}
if (unlikely(written < 0))
return -1;
if (unlikely(written == 0))
return -1;
count -= written;
p += written;
sum += written;
}
return sum;
}
#endif
#include "htime.h"
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <signal.h>
#include "mysocket.h"
int init_server(int port);
void *recv_work(void *data);
void sig_handler(int signo);
int main(int argc, char *argv[])
{
if(argc != 2)
{
fprintf(stderr, "usage: server port\n");
return 0;
}
int fd = init_server(atoi(argv[1]));
if(fd < 0)
{
fprintf(stderr, "server start failed\n");
return 0;
}
int client;
while(1)
{
fprintf(stderr, "%s waiting for client...\n", gettime());
client = accept(fd, NULL, NULL);
if(client == -1)
{
fprintf(stderr, "%s accept failed : %m\n", gettime());
continue;
}
pthread_t pid;
pthread_create(&pid, NULL, recv_work, &client);
}
}
void *recv_work(void *data)
{
int fd = *(int*)data, ret, len=0;
fprintf(stderr, "client fd: %d\n", fd);
char *buf = NULL;
while(1)
{
ret = net_read(fd, &len, sizeof(int));
fprintf(stderr, "get info from client: %d(%d byte)[%m]\n", len, ret);
if(ret == 0) {
fprintf(stderr, "%s read 0, client seems to be dead...\n", gettime());
break;
} else if(ret < 0) {
fprintf(stderr, "ret=%d, errno=%d:%m\n",ret, errno);
if (errno == EINTR) continue;
if (errno == EAGAIN)
fprintf(stderr, "would block or time out\n");
} else {
buf = malloc(len); if(!buf) {fprintf(stderr, "OOM\n"); break;}
ret = net_read(fd, buf, len);
fprintf(stderr, "get data from client ret:%d ", ret);
if ( ret > 20 ) {
char t[20] = {};
memcpy(t, buf, 20);
fprintf(stderr, "(%s)\n", t);
}
ret = net_write(fd, &ret, sizeof(int));
// free(buf);
// buf = NULL;
}
}
fprintf(stderr, "close client fd: %d\n", fd);
pthread_detach(pthread_self());
pthread_exit(NULL);
}
void sig_handler(int signo)
{
fprintf(stderr, "receivec sig: %d\n", signo);
}
int init_server(int port)
{
struct sockaddr_in ser;
int fd, value = 1;
struct linger linger_opt = {1, 0};
ser.sin_family = AF_INET;
ser.sin_port = htons(port);
ser.sin_addr.s_addr = INADDR_ANY;
bzero(&(ser.sin_zero), 8);
fd = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(fd, SOL_SOCKET, SO_LINGER, &linger_opt,
sizeof(linger_opt));
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value));
if(bind(fd, (struct sockaddr*)&ser, sizeof(struct sockaddr))== -1)
{
fprintf(stderr, "bind error\n");
return -1;
}
if (listen(fd, 20) == -1){
fprintf(stderr, "listening failed\n");
return -1;
}
signal(SIGPIPE, sig_handler);
return fd;
}
#include "htime.h"
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <signal.h>
#include "mysocket.h"
void *recv_work(void *data);
void sig_handler(int signo);
int main(int argc, char *argv[])
{
int p1=8888, p2=8889;
int fd;
if (argc == 2)
fd = connect_to(argv[1], p1);
else
fd = connect_to("10.254.4.23", p1);
if(fd < 0)
{
// fprintf(stderr, "server start failed\n");
return 0;
}
signal(SIGPIPE, sig_handler);
int MAX = 1024*1024*10;
char *buf = malloc(MAX);// 20MB
if (buf == NULL) { fprintf(stderr, "OOM\n"); return 0;}
int ret;
while(1)
{
fprintf(stderr, "press ENTER to continue...");
getchar();
strcpy(buf,gettime());
printf("%s\n", gettime());
ret = net_write(fd, &MAX, sizeof(int));
if (ret != sizeof(int)) {
fprintf(stderr, "%s write failed pos1: ret=%d\n", gettime(), ret);
// continue;
}
ret = net_write(fd, buf, MAX);
if (ret != MAX) {
fprintf(stderr, "%s write failed pos2: ret=%d\n", gettime(), ret);
// continue;
}
int rsp = -1;//
ret = net_read(fd, &rsp, sizeof(int));
fprintf(stderr, "%s ", gettime());
if (rsp != MAX) {
fprintf(stderr, "rsp error: ret=%d,rsp=%d,req=%d \n", ret, rsp, MAX);
} else {
fprintf(stderr, "req & rsp is ok(data length: %d) \n", rsp);
}
}
}
void sig_handler(int signo)
{
fprintf(stderr, "receivec sig: %d\n", signo);
}
/* [~]# cat test.c */
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <time.h>
char buf[1024 * 1024 * 10];
int main()
{
int fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr = {
.sin_family = AF_INET,
.sin_addr.s_addr = htonl(0x7f000001),
.sin_port = htons(10000),
};
struct timeval tv = {
.tv_sec = 5,
};
int n;
n = setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
printf("SO_SNDTIMEO=%d\n", n);
n = connect(fd, (void *)&addr, sizeof(addr));
printf("connect=%d\n", n);
if (n < 0)
return 1;
printf("wait 5s...\n");
sleep(5);
printf("begin write..\n");
time_t t1, t2;
t1 = time(NULL);
n = write(fd, buf, sizeof buf);
t2 = time(NULL);
printf("write=%d/%d in %ds\n", n, sizeof buf, t2 - t1);
return 0;
}
/*
[~]# nc -ldv 127.0.0.1 10000 &
[1] 7031
[~]# ./test &
[2] 7032
[~]# SO_SNDTIMEO=0
connect=0
wait 5s...
Connection from 127.0.0.1 port 10000 [tcp/ndmp] accepted
[~]# iptables -A OUTPUT -p tcp --dport 10000 -j DROP <---------- 用DROP丢包模拟拔断网线
[~]# begin write..
write=49152/10485760 in 5s <----- 没有出现两倍的超时现象,但write确实只写了一部分。
*/