#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> /* basic system data types */
#include <sys/socket.h> /* basic socket definitions */
#include <netinet/in.h> /* sockaddr_in{} and other Internet defns */
#include <arpa/inet.h> /* inet(3) functions */
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#define MAXSLEEP 128
#define CONNECT_TEST 255
typedef void (*SIG_FUNC)(int);
void sigpipe_handler(int sig)
{
printf("Get signal PIPE!\n");
}
ssize_t /* Read "n" bytes from a descriptor. */
readn(int fd, void *vptr, size_t n)
{
size_t nleft;
ssize_t nread;
char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nread = read(fd, ptr, nleft)) < 0) {
printf("rc < 0, errno = %d\n", errno);
if (errno == EINTR)
nread = 0;/* and call read() again */
else
return(-1);
} else if (nread == 0) {
//printf("nread = 0\n");
break; /* EOF */
}
nleft -= nread;
ptr += nread;
}
return(n - nleft); /* return >= 0 */
}
ssize_t /* Write "n" bytes to a descriptor. */
writen(int fd, const void *vptr, size_t n)
{
size_t nleft;
ssize_t nwritten;
const char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
printf("nwritten= %d\n",nwritten);
if (nwritten < 0 && errno == EINTR)
nwritten = 0; /* and call write() again */
else
return(-1); /* error */
}
printf("nwritten= %d\n",nwritten);
nleft -= nwritten;
ptr += nwritten;
}
return(n);
}
int
connect_retry(int domain, int type, int protocol, const struct sockaddr * addr, socklen_t alen)
{
int numsec, fd;
/*
* try to connect with exponential backoff
* if connect failed , should socket again
*/
for (numsec = 1; numsec <= MAXSLEEP; numsec <<= 1)
{
if ((fd = socket(domain, type, protocol)) < 0)
{
printf("socket error!\n");
return -1;
}
if (connect(fd, addr, alen) == 0)
{
/*
* connect accept,return success
*/
return fd;
}
close(fd);
/*delay before trying again*/
if (numsec <= MAXSLEEP/2)
{
sleep(numsec);
}
}
return -1;
}
int client_process(int fd)
{
char buf[100];
printf("client sleep 10 second and write 100 bytes\n");
sleep(10);
writen(fd, buf, 100);
writen(fd, buf, 100);/*generate SIGPIPE */
while(1);
return 0;
}
/*
* Set signal handler for SIGCHLD,to wait child process,clean zombies
*/
int set_signal(int signo, SIG_FUNC func)
{
struct sigaction act, oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (signo == SIGALRM)
{
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT; /* SunOS 4.x */
#endif
}
else //Only SIGALRM can interrupt the system call, otherwise we restart system call
{
#ifdef SA_RESTART
act.sa_flags |= SA_RESTART; /* SVR4, 44BSD */
#endif
}
if (sigaction(signo, &act, &oact) < 0)
return(-1);
return 0;
}
void usage()
{
printf("Useage: client [-a IPaddress] [-p port]\n");
}
/*
* we can also use getaddrinfo() function to get (ip and port)
* from (hostname and servername)
*/
int main(int argc, char *argv[])
{
struct sockaddr_in connect_addr;
int connect_fd, opt, n, command = -1;
memset(&connect_addr, 0, sizeof(connect_addr));
//set default IP address and port
connect_addr.sin_family = AF_INET;
connect_addr.sin_port = htons(3333);
if (inet_aton("127.0.0.1",(struct in_addr*)&(connect_addr.sin_addr.s_addr)) == 0){
printf("inet_aton error!\n");
exit(1);
}
/*
**use getopt() function to handle argv[]
** (global variables)
** optarg: when getopt() return, if the opt has a arg, it will be set to optarg
** opterr: not 0,will print error message; 0,will not print error message
** optind: the index of next argv after while loop
** optopt: when find a invalid opt, getopt() returns '?' or ':', and the invalid opt is set to optopt
**
*/
while ((opt = getopt(argc, argv, "a:p:h")) != EOF){
switch(opt) {
case 'a':
if (inet_aton(optarg,(struct in_addr*)&(connect_addr.sin_addr.s_addr)) == 0)
{
printf("inet_aton error!\n");
exit(1);
}
printf("connect IP address = %s\n", optarg);
break;
case 'p':
{
int port;
if (sscanf(optarg, "%d", &port) != 1)
{
printf("port argv error!\n");
exit(1);
}
connect_addr.sin_port = htons(port);
printf("connect port = %d\n", port);
break;
}
case 'h':
usage();
exit(0);
default:
usage();
exit(0);
}
}
printf("optind=%d\n",optind);
n = argc - optind;
if (n != 0){
usage();
exit(1);
}
/*config net connect*/
if (set_signal(SIGPIPE, sigpipe_handler) == -1)
{
printf("signal SIGPIPE set error!\n");
exit(1);
}
connect_fd = connect_retry(AF_INET, SOCK_STREAM, 0,
(struct sockaddr *)&connect_addr, sizeof(connect_addr));
if (connect_fd < 0)
{
printf("connect server failed!\n");
exit(1);
}
client_process(connect_fd);
exit(0);
}
一个简单网络客户端demo示例
猜你喜欢
转载自blog.csdn.net/rikeyone/article/details/80973918
今日推荐
周排行