解决Linux 下server和client 通过TCP通讯:accept成功接收却报错的问题

  今天在写简单的TCP通讯例子的时候,遇到了一个问题:server 和client能够连接成功,并且client也能够正常发送,但server就是接收不到,在网上搜索一番后,终于解决了问题。在这里整理如下:

  大家要注意的是,一个server端可以连接多个client端,server端的accept()函数负责等待并接收client的连接请求,而且accept()函数将不同client端的sockfd作为返回值。为了保证接收到对应的client端数据,所以在client连接成功且使用recv()函数接收数据的时候,recv()函数的第一个参数应该是accept成功后的返回值。

实例代码如下:

1.server端

 1 #include <sys/types.h>
 2 #include <sys/socket.h>
 3 #include <stdio.h>
 4 #include <stdlib.h>
 5 #include <string.h>
 6 #include <errno.h>
 7 #include <unistd.h>
 8 #include <netinet/in.h>
 9 #include <netdb.h>
10
11 #define MAX_MSG_LEN 1024
12 #define BACKLOG     10
13
14 int main(int argc,char *arg[])
15 {
16     struct sockaddr_in servAddr,clidAddr;
17     struct hostent *host = NULL;
18     int Port = 0,socketFd,sin_size;
19     socklen_t peerlen;
20     int recLen = 0;
21     char buf[MAX_MSG_LEN] = {0};
22
23     if(argc<2)
24     {
25         printf("please input port number!\r\n");
26         return -1;
27     }
28
29     //                     ipV4        TCP     0
30     if((socketFd=socket(AF_INET,SOCK_STREAM,0))==-1)
31     {
32         perror("socket");
33         return -1;
34     }
35     printf("socket fd = %d\n",socketFd);
36
37
38     memset(&servAddr,0,sizeof(struct sockaddr_in));
39     servAddr.sin_family = AF_INET;
40     servAddr.sin_port   = htons(atoi(arg[1]));
41     servAddr.sin_addr.s_addr= INADDR_ANY;
42
43     if(bind(socketFd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr))==-1)
44     {
45         perror("bind:");
46     }
47     else
48     {
49         printf("bind success \r\n");
50     }
51
52     if(listen(socketFd,BACKLOG)==-1)
53     {
54         perror("listen:");
55     }
56     else
57     {
58         printf("Listening...\r\n");
59     }
60     sin_size=sizeof(struct sockaddr_in);
61
62     if((socketFd=accept(socketFd,(struct sockaddr *)&clidAddr,&sin_size))==-1)
63     {
64             perror("accept:");
65             return -1;
66     }
67         else
68     {
69             printf("accept successful!\r\n");
70     }
71
72     while(1)
73     {
74         memset(buf,0,sizeof(buf));
75         if((recLen = recv(socketFd,buf,MAX_MSG_LEN,0))==-1)
76         {
77             perror("recv:");
78         }
79         else
80         {
81             if(recLen>0)
82             {
83                 recLen = 0;
84                 printf("Receive a message:%s\r\n",buf);
85             }
86         }
87     }
88     close(socketFd);
89     return 0;
90 }

上述代码的关键在于62行:

if((socketFd=accept(socketFd,(struct sockaddr *)&clidAddr,&sin_size))==-1)
recv(socketFd,buf,MAX_MSG_LEN,0);
将sockfd赋值为accept的返回值问题就解决了,为了实验方便,这里一并附上client代码:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netdb.h>

#define MAX_MSG_LEN 1024

int main(int argc,char *arg[])
{
    struct sockaddr_in servAddr;
    struct hostent *host = NULL;
    int Port = 0,socketFd;
    char buf[MAX_MSG_LEN] = {0};

    if(argc<3)
    {
        printf("please input IP and port number!\r\n");
        return -1;
    }

    if((host = gethostbyname(arg[1]))==NULL)
    {
        return -1;
    }
    //                     ipV4        TCP     0
    if((socketFd=socket(AF_INET,SOCK_STREAM,0))==-1)
    {
        perror("socket");
        return -1;
    }
    printf("socket fd = %d\n",socketFd);
    memset(&servAddr,0,sizeof(struct sockaddr_in));
    servAddr.sin_family = AF_INET;
    servAddr.sin_port   = htons(atoi(arg[2]));
    servAddr.sin_addr    = (*(struct in_addr *)host->h_addr);

    if(connect(socketFd,(struct sockaddr *)&servAddr,sizeof(struct sockaddr))==-1)
    {
        perror("connect:");
        return -1;
    }

    while(1)
    {
        printf("input:");
        scanf("%s",buf);
        if(send(socketFd,buf,sizeof(buf),0)==-1)
        {
            perror("send:");
        }
        {
            printf("send successful!\r\n");
        }
        memset(buf,0,sizeof(buf));
    }
    close(socketFd);
    return 0;
}
 
时间: 2024-12-27 21:12:02

解决Linux 下server和client 通过TCP通讯:accept成功接收却报错的问题的相关文章

Linux下编译程序时,经常会遇到“undefined reference to XXX” 报错,

Linux下编译程序时,经常会遇到“undefined reference to XXX” 报错, 这里总结一些可能的原因和解决方案,给需要的朋友: 说道undefined reference error,先提一下Linux gcc链接规则: 链接的时候查找顺序是: -L 指定的路径, 从左到右依次查找 由 环境变量 LIBRARY_PATH 指定的路径,使用":"分割从左到右依次查找 /etc/ld.so.conf 指定的路径顺序 /lib 和 /usr/lib (64位下是/lib

Linux下socket编程,附带tcp例子

1.网络中进程之间如何通信? 本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的和具名的) 远程过程调用(Solaris门和Sun RPC) 但这些都不是本文的主题!我们要讨论的是网络中进程之间如何通信?首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的.其实TCP/IP协议族已经帮我们解决了这个问

Linux 下配置 SoftEther Client

我经常使用的代理有 SSH, GoAgent, FreeGate, VPN, HttpProxy 等等,不过 SoftEther 应该是我用过的最快.最稳定的 VPN 协议. Windows 下配置 SoftEther 就不叙述了,实在太简单了,稍微有点计算机基础的人都能配置起来. 我经常工作于 Windows 和 Linux 下,而 Linux 下只有基于 CLI 的管理方式,并且在路由配置上需要自己手动解决,难度可想而知. 如果有朋友在 Linux 下配置 SoftEther 时遇到问题,不

如何解决linux下apache启动时httpd: apr_sockaddr_info_get() failed for 报错

今天在家里的RHLE5.5上安装apache的时候,先用user1用户./configure命令配置,然后才用root用户make && make install,结果apache起来的时候就报如下错误: httpd: apr_sockaddr_info_get() failed for bogon httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 fo

解决Linux下Svn检出Windows SVN服务器上项目SSL handshake failed: SSL error: Key usage violation in certificate has been detected.

在Linux上检出windows SVN服务器上项目时出现了SSL handshake failed: SSL error: Key usage violation in certificate has been detected.的错误. 最后通过从网上检索找到了一个答案: 可以同时解决掉在Ubuntu上和CentOS上检出失败的问题. 在Windows注册表中加入注册项: 32位机器: [HKEY_LOCAL_MACHINE\SOFTWARE\VisualSVN\VisualSVN Serv

解决Linux下乱码

1,设置Xshell编码为utf8 2,修改~/.bash_profile,添加 ? 1 export LANG=zh_CN.utf8 执行命令 ? 1 $source ~/.bash_profile 解决~ 解决Linux下乱码,布布扣,bubuko.com

解决Linux下Tomcat日志目录下的catalina.log日志文件过大的问题

本文摘自:(http://blog.csdn.net/stevencn76/article/details/6246162) 分类: Java技术专区2011-03-13 12:25 5017人阅读 评论(1) 收藏 举报 tomcatlinux工具任务web 由于Tomcat在默认情况下会将没有经过配置的web应用所产生的日志输出已经其本身的日志内容都输出到这个文件中,那么随着时间的推移,这个文件的尺寸将会越来越大,当需要检查日志内容时间会导致文件难以打开,而且同时tomcat依旧在不断的向文

rlwrap: command not found和解决linux下sqlplus 提供浏览历史命令行的功能

rlwrap工具可以解决linux下sqlplus 提供浏览历史命令行的功能,和删除先前输入错误的字母等问题 1.安装 需要readline包 这个安装光盘就有 [[email protected] RedHat]# cd RPMS/[[email protected] RPMS]# rpm -Uvh readline*warning: readline-4.3-13.i386.rpm: V3 DSA signature: NOKEY, key ID db42a60eerror: Failed

解决linux下cocos2dx不能播放声音

cocos2dx2.2.1在linux下引用#include "SimpleAudioEngine.h",报错找不到该文件. 修改makefile文件,添加 SHAREDLIBS += -lcocosdenshion COCOS_LIBS +=$(LIB_DIR)/linux/release/libcocosdenshion.so 并将cocos2d-x-2.2.1/CocosDenshion/include目录下的SimpleAudioEngine.h和Export.h拷贝到ecli