免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: xinuaile2003
打印 上一主题 下一主题

【求助】socket编程,TCP连接 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2009-03-06 10:43 |只看该作者
原帖由 墨小白 于 2009-3-6 09:57 发表
我说的是正常退出情况下  recv函数会返回0

对于非法退出的话 可以设置一个心跳机制

client每间隔M秒发一个心跳包给server
若连续N秒server端没有收到client的心跳包,则认为client已经去见马克思了



我的客户端使用的是ie浏览器,是改不了了

论坛徽章:
0
12 [报告]
发表于 2009-03-06 14:12 |只看该作者

回复 #9 xinuaile2003 的帖子

你这样这次露出个脚丫子、下次露出个手指头的有谁看得懂啊

总要把一些关键给别人看才能帮你啊。你用GDB测试一下,或者在代码中加上捕获异常信号的处理看一看。不明白的是你的线程函数的入口参数是啥,malloc的,还是?

论坛徽章:
0
13 [报告]
发表于 2009-03-06 14:18 |只看该作者

回复 #11 xinuaile2003 的帖子

如果你做WEB服务器的话有一些标准的做法的,如果客户端用connection:close,或你想强制用这种方式,发完了简单关闭socket就可以了;如果想用keep-alive,一般是发完数据之后等一会儿,看客户端会不会在同一个socket上再次请求,如果请求继续执行,否则关闭连接。

论坛徽章:
0
14 [报告]
发表于 2009-03-09 13:34 |只看该作者
好好看看STEVEN的网络编程第一卷,前几张,由浅入深,一步一步改造你的程序到最佳状态。上面都有。

论坛徽章:
0
15 [报告]
发表于 2009-03-13 10:51 |只看该作者
把send(netsndclifd, (char *)(we.encodedBuffer + i * 1400), 1400, 0)改成
send(netsndclifd, (char *)(we.encodedBuffer + i * 1400), 1400, MSG_NOSIGNAL),现在是不会自动退出了,只是不知道会不会出现什么后遗症。

论坛徽章:
0
16 [报告]
发表于 2009-03-13 10:55 |只看该作者
给你一个正确的serverside。
/* serverside.c - a simple server application */

/* Copyright 1984-2006 Wind River Systems, Inc. */

/*
modification history
--------------------
01a,12oct06,d_c   written.
*/

/* include */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>

/* globals */

/* message to be sent to client on a connect */
const char MESSAGE[] = "Hello, World!\n";

/* set the maximum length the queue of pending connections may grow to */
const int BACK_LOG = 5;

int main(int argc, char *argv[])
        {
        int serverSocket = 0;
        int enablePortReuse = 0;
        int serverPort = 0;
        int status = 0;
        int childPid = 0;
        char hostname[80] = "";

        struct hostent *hostPtr = NULL;
        struct sockaddr_in serverName = { 0 };
        struct linger linger = { 0 };

        /* read & validata input parameters */
        if (argc != 2)
                {
                fprintf(stderr, "Usage: serverside <port>\n");
                exit(-1);
                }

        serverPort = atoi(argv[1]);

        if (serverPort < 0)
                {
                fprintf(stderr, "serverside: strange serverPort value specified\n");
                exit (-1);
                }

        if ( (serverSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 )
                {
                fprintf(stderr, "serverside: error calling socket()\n");
                exit (-1);
                }

        /* setup and enable listening */
        enablePortReuse = 1;

        if ( (status = setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR,
                (const char *) &enablePortReuse, sizeof(enablePortReuse))) == -1)
                {
                fprintf(stderr, "serverside: warning, setting SO_REUSEADDR failed\n");
                }

        linger.l_onoff = 1;
        linger.l_linger = 30;

        if ( (status = setsockopt(serverSocket, SOL_SOCKET, SO_LINGER, (const char *) &linger,
                sizeof(linger))) == -1)
                {
                fprintf(stderr, "serverside: warning, setting SO_LINGER failed\n");
                }

        if ( (status = gethostname(hostname, sizeof(hostname))) == -1 )
                {
                fprintf(stderr, "serverside: error calling gethostname()\n");
                exit (-1);
                }

        if ( (hostPtr = gethostbyname(hostname)) == NULL )
                {
                fprintf(stderr, "serverside: error calling gethostbyname(%s)\n", hostname);
                exit (-1);
                }

        (void) memset(&serverName, 0, sizeof(serverName));
        (void) memcpy(&serverName.sin_addr, hostPtr->h_addr, hostPtr->h_length);

        serverName.sin_family = AF_INET;
        serverName.sin_port = htons(serverPort);

        if ( (status = bind(serverSocket, (struct sockaddr *) &serverName, sizeof(serverName))) == -1 )
                {
                fprintf(stderr, "serverside: error calling bind()\n");
                exit (-1);
                }

        if ( (status = listen(serverSocket, BACK_LOG)) == -1 )
                {
                fprintf(stderr, "serverside: error calling listen()\n");
                exit (-1);
                }

        /* wait for connection */

        while (1)
                {
                struct sockaddr_in clientName = { 0 };
                int clientSocket = 0;
                int clientLength = sizeof(clientName);

                (void) memset(&clientName, 0, sizeof(clientName));

                if ( (clientSocket = accept(serverSocket, (struct sockaddr *) &clientName,
                        &clientLength)) == -1 )
                        {
                        fprintf(stderr, "serverside: error calling accept()\n");
                        exit (-1);
                        }

                /* for each connection accepted, start a new process. this way we can
                   accept multiple connections */
                childPid = fork();

                switch (childPid)
                        {
                        case -1:

                                fprintf(stderr, "serverside: error calling fork()\n");
                                exit (-1);

                        case 0:

                                /* the child process. this is where we reply to the
                                   client's message */
                                close(serverSocket);

                                /* insert on_line() */ write(clientSocket, MESSAGE, strlen(MESSAGE));

                                close(clientSocket);

                                /* close this child process as task is done */
                                exit(0);

                        default:

                                /* the parent process */
                                close(clientSocket);
                        }
                }

        return 0;
        }

论坛徽章:
0
17 [报告]
发表于 2009-03-13 10:55 |只看该作者
在给你一个正确的clientside

/* clientside.c - a simple client application for the server */

/* Copyright 1984-2006 Wind River Systems, Inc. */

/*
modification history
--------------------
01a,12oct06,d_c   written.
*/

/* include */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <time.h>
#include <syslog.h>

/* defines */

#ifndef NSEC_PER_SEC
#define NSEC_PER_SEC 1000000000L
#endif
#define NUM_SAMPLES 1000

typedef unsigned long nsec_t;

nsec_t getNsecTimeDiff(struct timespec *before_time, struct timespec *after_time);
nsec_t timespecToNs(struct timespec *ts);

int main(int argc, char *argv[])
        {
        int clientSocket = 0;
        int serverPort   = 0;
        int status   = 0;
        char buffer[16]  = "";
        char *serverHost = NULL;
        nsec_t nsecDiff = 0;
        nsec_t average = 0;
        int count = 0;

        struct hostent *hostPtr = NULL;
        struct sockaddr_in serverName = { 0 };
        struct timespec before_time;
        struct timespec after_time;

        /* read & validata input parameters */
        if (argc != 3)
                {
                fprintf(stderr, "Usage: clientside <serverHost> <serverPort>\n");
                exit (-1);
                }

        serverHost = argv[1];
        serverPort = atoi(argv[2]);

        if (strlen(serverHost) < 1)
                {
                fprintf(stderr, "clientside: strange serverHost value specified\n");
                exit (-1);
                }

        if (serverPort < 0)
                {
                fprintf(stderr, "clientside: strange serverPort value specified\n");
                exit (-1);
                }

        /* count starts from 1 so we can start calculating average */
        for (count = 1; count <= NUM_SAMPLES; count++)
                {
                /* setup and enable sending */
                if ( (clientSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1 )
                        {
                        fprintf(stderr, "clientside: error opening socket\n");
                        exit (-1);
                        }


                if ( (hostPtr = gethostbyname(serverHost)) == NULL)
                        {
                        if ( (hostPtr = gethostbyaddr(serverHost, strlen(serverHost),
                                AF_INET)) == NULL )
                                {
                                fprintf(stderr, "clientside: error resolving server address\n");
                                exit (-1);
                                }
                        }

                serverName.sin_family = AF_INET;
                serverName.sin_port = htons(serverPort);

                (void) memcpy(&serverName.sin_addr, hostPtr->h_addr,
                        hostPtr->h_length);

                /* start timing operations */
                clock_gettime(CLOCK_REALTIME, &before_time);

                if ( (status = connect(clientSocket, (struct sockaddr*) &serverName,
                        sizeof(serverName))) == -1 )
                        {
                        fprintf(stderr, "clientside: error connecting %d\n", count);
                        exit (-1);
                        }

                while (0 < (status = read(clientSocket, buffer, sizeof(buffer) - 1)));

                if (status == -1)
                        {
                        fprintf(stderr, "clientside: error reading\n");
                        exit (-1);
                        }

                clock_gettime(CLOCK_REALTIME, &after_time);

                /* stop timing operations */

                nsecDiff = getNsecTimeDiff(&before_time, &after_time);

                average = ( (average * (count - 1) ) + nsecDiff ) / count ;

                close(clientSocket);
                }
        printf("%s",buffer);
        printf("avg for %d samples is 0x%lx ns or %lu ns\n", NUM_SAMPLES, average, average);

        return 0;
}

nsec_t getNsecTimeDiff(struct timespec *before_time, struct timespec *after_time)
        {
        nsec_t nsecDiff = timespecToNs(after_time) - timespecToNs(before_time);

        return nsecDiff;
        }

nsec_t timespecToNs(struct timespec *ts)
        {
        return ((nsec_t) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
        }

论坛徽章:
0
18 [报告]
发表于 2009-03-13 11:37 |只看该作者
原帖由 liying_gg 于 2009-3-13 10:55 发表
给你一个正确的serverside。
/* serverside.c - a simple server application */

/* Copyright 1984-2006 Wind River Systems, Inc. */

/*
modification history
--------------------
01a,12oct06,d ...




你使用的是创建一个进程(fork),而不是一个线程(phtread)。socket发送数据可以使用send函数不?

我的系统中有好几个线程呢,在其中一个线程使用fork函数,是不是会在子进程中创建所有的线程呢?

论坛徽章:
0
19 [报告]
发表于 2009-03-13 12:05 |只看该作者
服务器上处理errno=EINTR

论坛徽章:
0
20 [报告]
发表于 2009-03-14 00:58 |只看该作者
原帖由 xinuaile2003 于 2009-3-13 11:37 发表




你使用的是创建一个进程(fork),而不是一个线程(phtread)。socket发送数据可以使用send函数不?

我的系统中有好几个线程呢,在其中一个线程使用fork函数,是不是会在子进程中创建所有的线程呢?


按APUE中12.9的说法fork只会创建调用fork的那个线程。其实这个很容易测试的,你测试一下就知道了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP