日期:2014-05-16  浏览次数:20713 次

socket通信问题
在虚拟机下的fedora里面写了个server和client程序。
测试正常。现在想测试下怎么让网络上的client找到server。
然后向server发送信息。防火墙都关闭了。
虚拟机联网方式是nat。服务都开了。虚拟机里面的可以ping通
各个网站。现在就在怎么让client连接服务器了。求教育啊
server.c
C/C++ code

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define MAX 100

void deal(char *src)
{
    if (src == NULL)
        return ;

    for (; *src != '\0'; src++){
        if (*src >= 'A' && *src <= 'Z'){
            *src = *src - 'A' + 'a';
        }
    }
}

int main()
{
    struct sockaddr_in sin;
    struct sockaddr_in cin;
    int sockfd, cfd;
    socklen_t len;
    char buf[MAX];
    char addr_p[INET_ADDRSTRLEN];//存储客户端地址的缓冲区
    int port = 8000;
    int n;//读写字节数

    //对结构体清空
    bzero(&sin, sizeof(sin));
    sin.sin_family = AF_INET;//ipv4
    sin.sin_port = htons(port);//端口号转换为网络字节序
    sin.sin_addr.s_addr = INADDR_ANY;//服务器接受任意地址

    sockfd = socket(AF_INET, SOCK_STREAM, 0);//0表示使用默认的协议

    bind(sockfd, (struct sockaddr *)&sin, sizeof(sin));//将地址和套接字绑定

    listen(sockfd, 10);//监听,最多可以处理10个请求

    printf("waiting...\n");

    while (1){
        //接受连接,返回新创建的socket描述符
        cfd = accept(sockfd, (struct sockaddr *)&cin, &len);

        n = read(cfd, buf, MAX);//读取客户端传来的信息

        inet_ntop(AF_INET, &cin.sin_addr, addr_p, sizeof(addr_p));
        //将客户端地址转换为字符串
        printf("client IP is %s,port is %d\n", addr_p, ntohs(cin.sin_port));
        printf("content is : %s\n", buf);

        deal(buf);

        write(cfd, buf, n);//发给客户端

        printf("after deal the content is : %s\n", buf);

        close(cfd);//通讯结束,准备下一次通信
    }

    if (close(sockfd) == -1){
        perror("fail to close");
        exit(1);
    }

    exit(0);
}


client.c
C/C++ code

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

#define MAX 100

int main(int argc, char *argv[])
{
    struct sockaddr_in sin;//服务器地址

    char buf[MAX];
    int sockfd;
    int port = 8000;
    char *p = "test string";//默认字符串
    char *str = p;

    if (argc > 1){
        str = argv[1];
    }

    bzero(&sin, sizeof(sin));
    sin.sin_family = AF_INET;

    inet_pton(AF_INET, "192.168.1.1", &sin.sin_addr);
        //问题就在这里。当我把这个ip改为自己的网络ip,然后把客户端
         //放到网络上的另一台主机上。让它来连接服务器。但是没反应
         //不知道为啥
        //这里的ip应该为服务器的网络ip。但没写上去。就写了个私有ip
    sin.sin_port = htons(port);//和服务器同样的端口号

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
    connect(sockfd, (struct sockaddr *)&sin, sizeof(sin));
    //主动连接服务器
    write(sockfd, str, strlen(str) + 1);
    //该串不包括'\0'
    //读取服务器程序发回的串,由于是同一台机器,不存在延时
    //真正的网络环境,要处理延时
    read(sockfd, buf, MAX);

    printf("recive form server : %s\n", buf);

    close(sockfd);

    exit(0);
}



------解决方案--------------------
NAT只能帮助你的虚拟机LINUX上外网,局域网内其他机器和外网是无法主动连接你的,因为虚拟机根本不会把局域网机器发来的包NAT到你的虚拟机。

只有你的虚拟机主动连接外网的时候才会被NAT映射,所以楼主放弃吧。 我从没用过虚拟机软件设置NAT规则,里边有个PORT FORWARDING,也没看懂是不是修改NAT映射的地方,如果可以的话你就可以修改NAT规则,将流量以太网卡的XXX端口的包NAT到虚拟机网卡。