ipv6 socket

linux 专栏收录该内容
9 篇文章 0 订阅

LINUX 下 ipv6 socket 编程

发布: 2009-7-11 10:57 | 作者: admin | 来源: IPv6之家

大家都知道,随着互联网上主机数量的增多,现有的32位IP地址已经不够用了,所以推出了下一代IP地址IPv6,写网络程序的要稍微改变一下现有的网络程序适应IPv6网络是相当容易的事。
对于我们来说就是IP地址变化了,所以程序里在用到IP地址的地方做相应的改变就可以了。

记住:主要是改变程序里设置IP地址和端口等部分的代码。

服务器端源代码如下:
/***********************/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
#define MAXBUF 1024
/************关于本文档********************************************
*filename: ipv6-server.c
*purpose: 演示最基本的IPv6网络编程步骤,开启服务接收客户端连接并和客户端通信,互相收发消息
*wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
*date time:2007-01-29 13:06
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*Thanks to:Google
*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!

inet_aton() 转换网络主机地址cp为二进制数值,并存储在struct in_addr结构中,即第二个参数*inp,函数返回非0表示cp主机有地有效,返回0表示主机地址无效。
inet_addr函数转换网络主机地址(如192.168.1.10)为网络字节序二进制值,如果参数char *cp无效,函数返回-1(INADDR_NONE),这个函数在处理地址为255.255.255.255时也返回-1,255.255.255.255是一个有效的地址,不过inet_addr无法处理;
inet_ntoa 函数转换网络字节排序的地址为标准的ASCII以点分开的地址,,该函数返回指向点分开的字符串地址的指针,该字符串的空间为静态分配的,这意味着在第二次调用该函数时,上一次调用将会被重写(复盖),所以如果需要保存该串最后复制出来自己管理!
*********************************************************************/
int main(int argc, char **argv)
{
    int sockfd, new_fd;
    socklen_t len;
    /* struct sockaddr_in my_addr, their_addr; */ // IPv4
    struct sockaddr_in6 my_addr, their_addr; // IPv6
    unsigned int myport, lisnum;  //myport:端口号,lisnum最大连接数
    char buf[MAXBUF + 1];
    if (argv[1])
        myport = atoi(argv[1]);//atoi /把字符串转化为整形,
    else
        myport = 7838;
    if (argv[2])
        lisnum = atoi(argv[2]);
    else
        lisnum = 2;
    /* if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { */ // IPv4
    if ((sockfd = socket(PF_INET6, SOCK_STREAM, 0)) == -1) { // IPv6
        perror("socket");
        exit(1);
    } else
        printf("socket created\n");
    bzero(&my_addr, sizeof(my_addr));
    /* my_addr.sin_family = PF_INET; */ // IPv4
    my_addr.sin6_family = PF_INET6;    // IPv6
    /* my_addr.sin_port = htons(myport); */ // IPv4
    my_addr.sin6_port = htons(myport);   // IPv6  htons :将主机的无符号短整形数转 换成网络字节顺序。
    if (argv[3])
        /* my_addr.sin_addr.s_addr = inet_addr(argv[3]); */ // IPv4
        inet_pton(AF_INET6, argv[3], &my_addr.sin6_addr);  // IPv6
/*#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
int inet_pton(int af, const char *src, void *dst);

这个函数转换字符串到网络地址,第一个参数af是地址族,转换后存在dst中
inet_pton 是inet_addr的扩展,支持的多地址族有下列:

AF_INET
       src为指向字符型的地址,即ASCII的地址的首地址(ddd.ddd.ddd.ddd格式的),函数将该地址
       转换为in_addr的结构体,并复制在*dst中

AF_INET6
       src为指向IPV6的地址,,函数将该地址
       转换为in6_addr的结构体,并复制在*dst中
如果函数出错将返回一个负值,并将errno设置为EAFNOSUPPORT,如果参数af指定的地址族和src格式不对,函数将返回0。

函数inet_ntop进行相反的转换原型如下
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
这个函数转换网络二进制结构到ASCII类型的地址,参数的作用和上面相同,只是多了一个参数socklen_t cnt,他是所指向缓存区dst的大小,避免溢出,如果缓存区太小无法存储地址的值,则返回一个空指针,并将errno置为ENOSPC
*/
    else
        /* my_addr.sin_addr.s_addr = INADDR_ANY; */ // IPv4
        my_addr.sin6_addr = in6addr_any;            // IPv6
    /* if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) */ // IPv4
    if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr_in6))  // IPv6
        == -1) {
        perror("bind");
        exit(1);
    } else
        printf("binded\n");
    if (listen(sockfd, lisnum) == -1) {
        perror("listen");
        exit(1);
    } else
        printf("begin listen\n");
    while (1) {
        len = sizeof(struct sockaddr);
        if ((new_fd =
             accept(sockfd, (struct sockaddr *) &their_addr,
                    &len)) == -1) {
            perror("accept");
            exit(errno);
        } else
            printf("server: got connection from %s, port %d, socket %d\n",
                   /* inet_ntoa(their_addr.sin_addr), */ // Ipv4
               inet_ntop(AF_INET6, &their_addr.sin6_addr, buf, sizeof(buf)), // IPv6
                   /* ntohs(their_addr.sin_port), new_fd); */ // IPv4
                   their_addr.sin6_port, new_fd); // IPv6

        /* 开始处理每个新连接上的数据收发 */
        bzero(buf, MAXBUF + 1);
        strcpy(buf,
               "这是在连接建立成功后向客户端发送的第一个消息\n只能向new_fd这个用accept函数新建立的socket发消息,不能向sockfd这个监听socket发送消息,监听socket不能用来接收或发送消息\n");
        /* 发消息给客户端 */
        len = send(new_fd, buf, strlen(buf), 0);
        if (len < 0) {
            printf
                ("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n",
                 buf, errno, strerror(errno));
        } else
            printf("消息'%s'发送成功,共发送了%d个字节!\n",
                   buf, len);

        bzero(buf, MAXBUF + 1);
        /* 接收客户端的消息 */
        len = recv(new_fd, buf, MAXBUF, 0);
        if (len > 0)
            printf("接收消息成功:'%s',共%d个字节的数据\n",
                   buf, len);
        else
            printf
                ("消息接收失败!错误代码是%d,错误信息是'%s'\n",
                 errno, strerror(errno));
        /* 处理每个新连接上的数据收发结束 */
    }

    close(sockfd);
    return 0;
}

每行程序后面的 “//IPv4” 表示这行代码是在IPv4网络里用的
而“//IPv6” 表示这行代码是在IPv6网络里用的,比较一下,会很容易看到差别的。

客户端源代码如下:
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>                     //?
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define MAXBUF 1024
/************关于本文档********************************************
*filename: ipv6-client.c
*purpose: 演示最基本的IPv6网络编程步骤,这是个客户端程序,与服务器互相收发消息
*wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
*date time:2007-01-29 12:56
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*Thanks to:Google
*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
*********************************************************************/
int main(int argc, char **argv)
{
    int sockfd, len;
    /* struct sockaddr_in dest; */ // IPv4
    struct sockaddr_in6 dest;      // IPv6
    char buffer[MAXBUF + 1];
    if (argc != 3) {
        printf
            ("参数格式错误!正确用法如下:\n\t\t%s IP地址 端口\n\t比如:\t%s 127.0.0.1 80\n此程序用来从某个 IP 地址的服务器某个端口接收最多 MAXBUF 个字节的消息",
             argv[0], argv[0]);
        exit(0);
    }
    /* 创建一个 socket 用于 tcp 通信 */
    /* if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { */ // IPv4
    if ((sockfd = socket(AF_INET6, SOCK_STREAM, 0)) < 0) {      // IPv6
        perror("Socket");
        exit(errno);

  }
    printf("socket created\n");

    /* 初始化服务器端(对方)的地址和端口信息 */
    bzero(&dest, sizeof(dest));
    /* dest.sin_family = AF_INET; */  // IPv4
    dest.sin6_family = AF_INET6;     // IPv6
    /* dest.sin_port = htons(atoi(argv[2])); */ // IPv4
    dest.sin6_port = htons(atoi(argv[2]));     // IPv6
    /* if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) { */ // IPv4
    if ( inet_pton(AF_INET6, argv[1], &dest.sin6_addr) < 0 ) {                 // IPv6
        perror(argv[1]);
        exit(errno);
    }
    printf("address created\n");

    /* 连接服务器 */
    if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {
        perror("Connect ");
        exit(errno);
    }
    printf("server connected\n");

    /* 接收对方发过来的消息,最多接收 MAXBUF 个字节 */
    bzero(buffer, MAXBUF + 1);
    /* 接收服务器来的消息 */
    len = recv(sockfd, buffer, MAXBUF, 0);
    if (len > 0)
        printf("接收消息成功:'%s',共%d个字节的数据\n",
               buffer, len);
    else
        printf
            ("消息接收失败!错误代码是%d,错误信息是'%s'\n",
             errno, strerror(errno));

    bzero(buffer, MAXBUF + 1);
    strcpy(buffer, "这是客户端发给服务器端的消息\n");
    /* 发消息给服务器 */
    len = send(sockfd, buffer, strlen(buffer), 0);
    if (len < 0)
        printf
            ("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n",
             buffer, errno, strerror(errno));
    else
        printf("消息'%s'发送成功,共发送了%d个字节!\n",
               buffer, len);

    /* 关闭连接 */
    close(sockfd);
    return 0;
}


编译程序用下列命令:
引用:
gcc -Wall ipv6-server.c -o ipv6server
gcc -Wall ipv6-client.c -o ipv6client



你自己的主机有IPv6地址吗?很多人会问,输入ifconfig命令看一下吧:
引用:
eth0      链路封装:以太网  硬件地址 00:14:2A:6D:5B:A5
          inet 地址:192.168.0.167  广播:192.168.0.255  掩码:255.255.255.0
          inet6 地址: fe80::214:2aff:fe6d:5ba5/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  跃点数:1
          接收数据包:30507 错误:0 丢弃:0 过载:0 帧数:0
          发送数据包:26797 错误:0 丢弃:0 过载:0 载波:0
          碰撞:0 发送队列长度:1000
          接收字节:31461154 (30.0 MiB)  发送字节:4472810 (4.2 MiB)
          中断:185 基本地址:0xe400

lo        链路封装:本地环回
          inet 地址:127.0.0.1  掩码:255.0.0.0
          inet6 地址: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  跃点数:1
          接收数据包:13 错误:0 丢弃:0 过载:0 帧数:0
          发送数据包:13 错误:0 丢弃:0 过载:0 载波:0
          碰撞:0 发送队列长度:0
          接收字节:1178 (1.1 KiB)  发送字节:1178 (1.1 KiB)



看到“inet6 地址:”这两行了吗?后面就是你的IPv6地址
关于IPv6地址类型,可以参考一下 [url=http://docs.hp.com/zh_cn/B3936-90083/aphs01.html]惠普主页上的技术文档资料“IPv6地址类型”


启动服务:
./ipv6server 7838 1
或者加上IP地址启动服务:
./ipv6server 7838 1 fe80::214:2aff:fe6d:5ba5/64

启动客户端测试一下:
./ipv6client ::1/128 7838

./ipv6client fe80::214:2aff:fe6d:5ba5/6 7838

[ 本帖最后由 zhoulifa 于 2007-1-29 13:34 编辑 ]


universes 回复于:2007-01-29 15:07:16

赞一个先!
本人也是搞IPV6的,不过不是开源,在公司做IPV6产品的开发。编写了公司ND(邻居发现)部分的全部代码。
另外修改了TELNET代码以适应IPV6。
感觉IPV6现在还不很成熟,有兴趣的话可以一起交流、学习!

arenxl 回复于:2007-01-29 15:18:38

以前关注过,不过还是等以后用的时候再继续研究吧。

zhoulifa 回复于:2007-01-29 17:37:46

to universes:
高人!
你有没有NDP协议rfc文档? 还是说NDP目前没有标准,只是大家各自按自己的协议在做?
如果有,可否发一份给我? zhoulifa@gmail.com
先谢谢了!

fxyxsl 回复于:2007-01-29 17:49:59

这个和windows环境下有什么不同?

再请教个问题:windows XP环境下如何获取本机的IP地址(IPv6的地址)?我试了很多方法,2003下可以,XP却始终不行~

converse 回复于:2007-01-29 18:13:13

LZ你好,我看了你发的几个帖子,感觉不错,建议你整理到一个帖子里面这样以后查找方便也便于将你的想法系列化.我给你加原创精华,谢谢.

yingen2006 回复于:2007-01-29 23:00:37

mark

大大狗 回复于:2007-01-29 23:45:06

强人

zhoulifa 回复于:2007-02-03 21:00:05

引用:原帖由 converse 于 2007-1-29 18:13 发表
LZ你好,我看了你发的几个帖子,感觉不错,建议你整理到一个帖子里面这样以后查找方便也便于将你的想法系列化.我给你加原创精华,谢谢.


感谢版主!我也想全部发到这里,但不知道怎样才能一次发完全部的,所以只挑了几个有代表性的放在这里。我原本是一系列“ Linux网络编程一步一步学”,共24篇,如下:

[url=http://zhoulifa.bokee.com/6062858.html] • Linux网络编程一步一步学-简单客户端编写

[url=http://zhoulifa.bokee.com/6062924.html]  • Linux网络编程一步一步学-绑定IP和端口

[url=http://zhoulifa.bokee.com/6062989.html] • Linux网络编程一步一步学-循环读取服务器上的数据

[url=http://zhoulifa.bokee.com/6063041.html]  • Linux网络编程一步一步学-设置非阻塞方式

[url=http://zhoulifa.bokee.com/6064410.html]  • Linux网络编程一步一步学-开启网络监听服务

[url=http://zhoulifa.bokee.com/6064418.html] • Linux网络编程一步一步学-接受客户端连接请求

[url=http://zhoulifa.bokee.com/6064468.html] • Linux网络编程一步一步学-向客户端发送消息

[url=http://zhoulifa.bokee.com/6064533.html]  • Linux网络编程一步一步学-客户端和服务器端互相收发消息

[url=http://zhoulifa.bokee.com/6065457.html]  • Linux网络编程一步一步学-UDP编程介绍

[url=http://zhoulifa.bokee.com/6065676.html]  • Linux网络编程一步一步学-UDP方式点对点通讯

[url=http://zhoulifa.bokee.com/6065720.html] • Linux网络编程一步一步学-UDP方式广播通讯

[url=http://zhoulifa.bokee.com/6066939.html] • Linux网络编程一步一步学-网络广播、组播与单播

[url=http://zhoulifa.bokee.com/6066993.html]  • Linux网络编程一步一步学-UDP组播

[url=http://zhoulifa.bokee.com/6067924.html]  • Linux网络编程一步一步学-同步聊天程序

[url=http://zhoulifa.bokee.com/6068027.html]  • Linux网络编程一步一步学-异步通讯聊天程序select

[url=http://zhoulifa.bokee.com/6069209.html]  • Linux网络编程一步一步学-编写一个HTTP协议的目录浏览和文件下载服务器

[url=http://zhoulifa.bokee.com/6071872.html] • Linux网络编程一步一步学-用C自己编写一个telnet服务器

[url=http://zhoulifa.bokee.com/6072092.html] • Linux网络编程一步一步学-网络编程函数说明-来自“永远的UNIX”

[url=http://zhoulifa.bokee.com/6073915.html]  • Linux下上网方法总结

[url=http://zhoulifa.bokee.com/6074014.html] • Linux网络编程一步一步学-利用OpenSSL提供的SSL操作函数进行加密通讯原始例子

[url=http://zhoulifa.bokee.com/6075800.html]  • Linux网络编程一步一步学-IPv6下网络编程步骤

[url=http://zhoulifa.bokee.com/6079174.html]  • Linux网络编程一步一步学-HTTPS客户端程序示例

[url=http://zhoulifa.bokee.com/6079257.html] • OpenSSL体系下使用密钥数字证书等

[url=http://zhoulifa.bokee.com/6081520.html] • Linux网络编程一步一步学-epoll同时处理海量连接的代码  编写一个服务器同时处理上万的网络连接,这对大量用户同时在线的编程相当重要。

[url=http://zhoulifa.bokee.com/6085904.html] • Linux网络编程一步一步学-加密通讯协议SSL研究 这对银行、证券等行业来说相当重要

[url=http://zhoulifa.bokee.com/6087775.html] •  Linux网络编程一步一步学-select详解

还请告诉我如何将此全部发到这里。

[ 本帖最后由 zhoulifa 于 2007-2-3 21:09 编辑 ]

converse 回复于:2007-02-03 22:32:46

>>还请告诉我如何将此全部发到这里。
汗,你就把帖子一个一个的贴在这个帖子里面就好了,我敢打赌会N热门的~~

zw2002 回复于:2007-02-03 22:51:53

是啊,支持

linternt 回复于:2007-02-03 23:51:24

现在有代码都实现IPV4和IPV6通用了,支持精神!

zhoulifa 回复于:2007-02-04 12:23:26

引用:原帖由 converse 于 2007-2-3 22:32 发表
>>还请告诉我如何将此全部发到这里。
汗,你就把帖子一个一个的贴在这个帖子里面就好了,我敢打赌会N热门的~~
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define MAXBUF 1024
/************关于本文档********************************************
*filename: simple-socket.c
*purpose: 演示最基本的网络编程步骤,这是个客户端程序
*wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
*date time:2007-01-23 19:41:54
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
*********************************************************************/
int main(int argc, char **argv)
{
    int sockfd;
    struct sockaddr_in dest;
    char buffer[MAXBUF];
    if (argc != 3) {
        printf
            ("参数格式错误!正确用法如下:\n\t\t%s IP地址 端口\n\t比如:\t%s 127.0.0.1 80\n此程序用来从某个 IP 地址的服务器某个端口接收最多 MAXBUF 个字节的消息",
             argv[0], argv[0]);
        exit(0);
    }
    /* 创建一个 socket 用于 tcp 通信 */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket");
        exit(errno);
    }
    /* 初始化服务器端(对方)的地址和端口信息 */
    bzero(&dest, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_port = htons(atoi(argv[2]));
    if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) {
        perror(argv[1]);
        exit(errno);
    }
    /* 连接服务器 */
    if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {
        perror("Connect ");
        exit(errno);
    }
    /* 接收对方发过来的消息,最多接收 MAXBUF 个字节 */
    bzero(buffer, MAXBUF);
    recv(sockfd, buffer, sizeof(buffer), 0);
    printf("%s", buffer);
    /* 关闭连接 */
    close(sockfd);
    return 0;
}

编译此程序使用如下命令:
引用:
gcc -Wall simple-socket.c


运行此程序使用如下命令(假设你的主机上开启了ssh服务):
引用:
./a.out 127.0.0.1 22



其实socket客户端编程相当简单:
第1步:建立一个socket句柄,用socket()函数;
第2步:设定你要连接的服务器的IP地址和端口等信息;
第3步:与服务器建立连接,用connect函数;
第4步:收发消息,用recv(sockfd,...)/send(sockfd,...)或者read(sockfd,...)/write(sockfd,...)都可以;
第5步:通讯结束后关闭连接,用close()函数即可,当然也有人用shutdown()函数。


[ 本帖最后由 zhoulifa 于 2007-2-4 12:48 编辑 ]

zhoulifa 回复于:2007-02-04 12:50:11

为了服务器的安全,有些服务器要求客户端只能以指定的IP地址和特定的端口才能连接上来。这就要求我们客户端连接之前绑定IP地址和端口信息。
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define MAXBUF 1024
/************关于本文档********************************************
*filename: simple-bind.c
*purpose: 演示最基本的网络编程步骤,这是个客户端程序以固定 IP 和端口连接服务器
*wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
*date time:2007-01-23 19:51:54
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
*********************************************************************/
int main(int argc, char **argv)
{
    int sockfd;
    struct sockaddr_in dest, mine;

char buffer[MAXBUF];

    if (argc != 5) {
        printf
            (" 参数格式错误!正确用法如下:\n\t\t%s 对方IP地址 对方端口 本机IP地址 本机端口\n\t比如:\t%s 127.0.0.1 80\n 此程序用来以本机固定的端口从某个 IP 地址的服务器某个端口接收最多 MAXBUF 个字节的消息",
             argv[0], argv[0]);
        exit(0);
    }
    /* 创建一个 socket 用于 tcp 通信 */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket");
        exit(errno);
    }

    /* 初始化服务器端(对方)的地址和端口信息 */
    bzero(&dest, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_port = htons(atoi(argv[2]));
    if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) {
        perror(argv[1]);
        exit(errno);
    }

    /* 初始化自己的地址和端口信息 */
    bzero(&mine, sizeof(mine));
    mine.sin_family = AF_INET;
    mine.sin_port = htons(atoi(argv[4]));
    if (inet_aton(argv[3], (struct in_addr *) &mine.sin_addr.s_addr) == 0) {
        perror(argv[3]);
        exit(errno);
    }

    /* 把自己的 IP 地址信息和端口与 socket 绑定 */
    if (bind(sockfd, (struct sockaddr *) &mine, sizeof(struct sockaddr)) ==
        -1) {
        perror(argv[3]);
        exit(errno);
    }

    /* 以自己特定的端口和IP连接服务器的特定端口 */
    if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {
        perror("Connect ");
        exit(errno);
    }

    /* 接收对方发过来的消息,最多接收 MAXBUF 个字节 */
    bzero(buffer, MAXBUF);
    recv(sockfd, buffer, sizeof(buffer), 0);
    printf("%s", buffer);
    sleep(10);
    /* 关闭连接 */
    close(sockfd);
    return 0;
}

编译程序用此命令:
引用:
gcc -Wall simple-bind.c


运行程序用此命令:
引用:
./a.out 127.0.0.1 22 127.0.0.1 3000


同时可以用下列netstat命令查看网络连接状态:
引用:
netstat -an|grep 3000


查看到如下信息:
引用:
tcp 0 0 127.0.0.1:3000 127.0.0.1:22 ESTABLISHED



与前面一份源代码相比,这里多了设置自己的IP地址和端口信息,所以编程过程变成了:
第1步:建立一个socket句柄,用socket()函数;
第2步:设定你要连接的服务器的IP地址和端口等信息;
第x步:设定你自己的IP地址和端口等信息与socket绑定,用bind()函数; #与前面相比就是多了这一个步骤
第3步:与服务器建立连接,用connect函数;
第4步:收发消息,用recv(sockfd,...)/send(sockfd,...)或者read(sockfd,...)/write(sockfd,...)都可以;
第5步:通讯结束后关闭连接,用close()函数即可,当然也有人用shutdown()函数。 char buffer[MAXBUF];

    if (argc != 5) {
        printf
            (" 参数格式错误!正确用法如下:\n\t\t%s 对方IP地址 对方端口 本机IP地址 本机端口\n\t比如:\t%s 127.0.0.1 80\n 此程序用来以本机固定的端口从某个 IP 地址的服务器某个端口接收最多 MAXBUF 个字节的消息",
             argv[0], argv[0]);
        exit(0);
    }
    /* 创建一个 socket 用于 tcp 通信 */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket");
        exit(errno);
    }

    /* 初始化服务器端(对方)的地址和端口信息 */
    bzero(&dest, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_port = htons(atoi(argv[2]));
    if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) {
        perror(argv[1]);
        exit(errno);
    }

    /* 初始化自己的地址和端口信息 */
    bzero(&mine, sizeof(mine));
    mine.sin_family = AF_INET;
    mine.sin_port = htons(atoi(argv[4]));
    if (inet_aton(argv[3], (struct in_addr *) &mine.sin_addr.s_addr) == 0) {
        perror(argv[3]);
        exit(errno);
    }

    /* 把自己的 IP 地址信息和端口与 socket 绑定 */
    if (bind(sockfd, (struct sockaddr *) &mine, sizeof(struct sockaddr)) ==
        -1) {
        perror(argv[3]);
        exit(errno);
    }

    /* 以自己特定的端口和IP连接服务器的特定端口 */
    if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {
        perror("Connect ");
        exit(errno);
    }

    /* 接收对方发过来的消息,最多接收 MAXBUF 个字节 */
    bzero(buffer, MAXBUF);
    recv(sockfd, buffer, sizeof(buffer), 0);
    printf("%s", buffer);
    sleep(10);
    /* 关闭连接 */
    close(sockfd);
    return 0;
}

编译程序用此命令:
引用:
gcc -Wall simple-bind.c


运行程序用此命令:
引用:
./a.out 127.0.0.1 22 127.0.0.1 3000


同时可以用下列netstat命令查看网络连接状态:
引用:
netstat -an|grep 3000


查看到如下信息:
引用:
tcp 0 0 127.0.0.1:3000 127.0.0.1:22 ESTABLISHED



与前面一份源代码相比,这里多了设置自己的IP地址和端口信息,所以编程过程变成了:
第1步:建立一个socket句柄,用socket()函数;
第2步:设定你要连接的服务器的IP地址和端口等信息;
第x步:设定你自己的IP地址和端口等信息与socket绑定,用bind()函数; #与前面相比就是多了这一个步骤
第3步:与服务器建立连接,用connect函数;
第4步:收发消息,用recv(sockfd,...)/send(sockfd,...)或者read(sockfd,...)/write(sockfd,...)都可以;
第5步:通讯结束后关闭连接,用close()函数即可,当然也有人用shutdown()函数。 char buffer[MAXBUF];

    if (argc != 5) {
        printf
            (" 参数格式错误!正确用法如下:\n\t\t%s 对方IP地址 对方端口 本机IP地址 本机端口\n\t比如:\t%s 127.0.0.1 80\n 此程序用来以本机固定的端口从某个 IP 地址的服务器某个端口接收最多 MAXBUF 个字节的消息",
             argv[0], argv[0]);
        exit(0);
    }
    /* 创建一个 socket 用于 tcp 通信 */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket");
        exit(errno);
    }

    /* 初始化服务器端(对方)的地址和端口信息 */
    bzero(&dest, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_port = htons(atoi(argv[2]));
    if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) {
        perror(argv[1]);
        exit(errno);
    }

    /* 初始化自己的地址和端口信息 */
    bzero(&mine, sizeof(mine));
    mine.sin_family = AF_INET;
    mine.sin_port = htons(atoi(argv[4]));
    if (inet_aton(argv[3], (struct in_addr *) &mine.sin_addr.s_addr) == 0) {
        perror(argv[3]);
        exit(errno);
    }

    /* 把自己的 IP 地址信息和端口与 socket 绑定 */
    if (bind(sockfd, (struct sockaddr *) &mine, sizeof(struct sockaddr)) ==
        -1) {
        perror(argv[3]);
        exit(errno);
    }

    /* 以自己特定的端口和IP连接服务器的特定端口 */
    if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {
        perror("Connect ");
        exit(errno);
    }

    /* 接收对方发过来的消息,最多接收 MAXBUF 个字节 */
    bzero(buffer, MAXBUF);
    recv(sockfd, buffer, sizeof(buffer), 0);
    printf("%s", buffer);
    sleep(10);
    /* 关闭连接 */
    close(sockfd);
    return 0;
}

编译程序用此命令:
引用:
gcc -Wall simple-bind.c


运行程序用此命令:
引用:
./a.out 127.0.0.1 22 127.0.0.1 3000


同时可以用下列netstat命令查看网络连接状态:
引用:
netstat -an|grep 3000


查看到如下信息:
引用:
tcp 0 0 127.0.0.1:3000 127.0.0.1:22 ESTABLISHED



与前面一份源代码相比,这里多了设置自己的IP地址和端口信息,所以编程过程变成了:
第1步:建立一个socket句柄,用socket()函数;
第2步:设定你要连接的服务器的IP地址和端口等信息;
第x步:设定你自己的IP地址和端口等信息与socket绑定,用bind()函数; #与前面相比就是多了这一个步骤
第3步:与服务器建立连接,用connect函数;
第4步:收发消息,用recv(sockfd,...)/send(sockfd,...)或者read(sockfd,...)/write(sockfd,...)都可以;
第5步:通讯结束后关闭连接,用close()函数即可,当然也有人用shutdown()函数。 char buffer[MAXBUF];

    if (argc != 5) {
        printf
            (" 参数格式错误!正确用法如下:\n\t\t%s 对方IP地址 对方端口 本机IP地址 本机端口\n\t比如:\t%s 127.0.0.1 80\n 此程序用来以本机固定的端口从某个 IP 地址的服务器某个端口接收最多 MAXBUF 个字节的消息",
             argv[0], argv[0]);
        exit(0);
    }
    /* 创建一个 socket 用于 tcp 通信 */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket");
        exit(errno);
    }

    /* 初始化服务器端(对方)的地址和端口信息 */
    bzero(&dest, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_port = htons(atoi(argv[2]));
    if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) {
        perror(argv[1]);
        exit(errno);
    }

    /* 初始化自己的地址和端口信息 */
    bzero(&mine, sizeof(mine));
    mine.sin_family = AF_INET;
    mine.sin_port = htons(atoi(argv[4]));
    if (inet_aton(argv[3], (struct in_addr *) &mine.sin_addr.s_addr) == 0) {
        perror(argv[3]);
        exit(errno);
    }

    /* 把自己的 IP 地址信息和端口与 socket 绑定 */
    if (bind(sockfd, (struct sockaddr *) &mine, sizeof(struct sockaddr)) ==
        -1) {
        perror(argv[3]);
        exit(errno);
    }

    /* 以自己特定的端口和IP连接服务器的特定端口 */
    if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {
        perror("Connect ");
        exit(errno);
    }

    /* 接收对方发过来的消息,最多接收 MAXBUF 个字节 */
    bzero(buffer, MAXBUF);
    recv(sockfd, buffer, sizeof(buffer), 0);
    printf("%s", buffer);
    sleep(10);
    /* 关闭连接 */
    close(sockfd);
    return 0;
}

编译程序用此命令:
引用:
gcc -Wall simple-bind.c


运行程序用此命令:
引用:
./a.out 127.0.0.1 22 127.0.0.1 3000


同时可以用下列netstat命令查看网络连接状态:
引用:
netstat -an|grep 3000


查看到如下信息:
引用:
tcp 0 0 127.0.0.1:3000 127.0.0.1:22 ESTABLISHED



与前面一份源代码相比,这里多了设置自己的IP地址和端口信息,所以编程过程变成了:
第1步:建立一个socket句柄,用socket()函数;
第2步:设定你要连接的服务器的IP地址和端口等信息;
第x步:设定你自己的IP地址和端口等信息与socket绑定,用bind()函数; #与前面相比就是多了这一个步骤
第3步:与服务器建立连接,用connect函数;
第4步:收发消息,用recv(sockfd,...)/send(sockfd,...)或者read(sockfd,...)/write(sockfd,...)都可以;
第5步:通讯结束后关闭连接,用close()函数即可,当然也有人用shutdown()函数。 char buffer[MAXBUF];

    if (argc != 5) {
        printf
            (" 参数格式错误!正确用法如下:\n\t\t%s 对方IP地址 对方端口 本机IP地址 本机端口\n\t比如:\t%s 127.0.0.1 80\n 此程序用来以本机固定的端口从某个 IP 地址的服务器某个端口接收最多 MAXBUF 个字节的消息",
             argv[0], argv[0]);
        exit(0);
    }
    /* 创建一个 socket 用于 tcp 通信 */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket");
        exit(errno);
    }

    /* 初始化服务器端(对方)的地址和端口信息 */
    bzero(&dest, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_port = htons(atoi(argv[2]));
    if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) {
        perror(argv[1]);
        exit(errno);
    }

    /* 初始化自己的地址和端口信息 */
    bzero(&mine, sizeof(mine));
    mine.sin_family = AF_INET;
    mine.sin_port = htons(atoi(argv[4]));
    if (inet_aton(argv[3], (struct in_addr *) &mine.sin_addr.s_addr) == 0) {
        perror(argv[3]);
        exit(errno);
    }

    /* 把自己的 IP 地址信息和端口与 socket 绑定 */
    if (bind(sockfd, (struct sockaddr *) &mine, sizeof(struct sockaddr)) ==
        -1) {
        perror(argv[3]);
        exit(errno);
    }

    /* 以自己特定的端口和IP连接服务器的特定端口 */
    if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {
        perror("Connect ");
        exit(errno);
    }

    /* 接收对方发过来的消息,最多接收 MAXBUF 个字节 */
    bzero(buffer, MAXBUF);
    recv(sockfd, buffer, sizeof(buffer), 0);
    printf("%s", buffer);
    sleep(10);
    /* 关闭连接 */
    close(sockfd);
    return 0;
}

编译程序用此命令:
引用:
gcc -Wall simple-bind.c


运行程序用此命令:
引用:
./a.out 127.0.0.1 22 127.0.0.1 3000


同时可以用下列netstat命令查看网络连接状态:
引用:
netstat -an|grep 3000


查看到如下信息:
引用:
tcp 0 0 127.0.0.1:3000 127.0.0.1:22 ESTABLISHED



与前面一份源代码相比,这里多了设置自己的IP地址和端口信息,所以编程过程变成了:
第1步:建立一个socket句柄,用socket()函数;
第2步:设定你要连接的服务器的IP地址和端口等信息;
第x步:设定你自己的IP地址和端口等信息与socket绑定,用bind()函数; #与前面相比就是多了这一个步骤
第3步:与服务器建立连接,用connect函数;
第4步:收发消息,用recv(sockfd,...)/send(sockfd,...)或者read(sockfd,...)/write(sockfd,...)都可以;
第5步:通讯结束后关闭连接,用close()函数即可,当然也有人用shutdown()函数。 char buffer[MAXBUF];

    if (argc != 5) {
        printf
            (" 参数格式错误!正确用法如下:\n\t\t%s 对方IP地址 对方端口 本机IP地址 本机端口\n\t比如:\t%s 127.0.0.1 80\n 此程序用来以本机固定的端口从某个 IP 地址的服务器某个端口接收最多 MAXBUF 个字节的消息",
             argv[0], argv[0]);
        exit(0);
    }
    /* 创建一个 socket 用于 tcp 通信 */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket");
        exit(errno);
    }

    /* 初始化服务器端(对方)的地址和端口信息 */
    bzero(&dest, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_port = htons(atoi(argv[2]));
    if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) {
        perror(argv[1]);
        exit(errno);
    }

    /* 初始化自己的地址和端口信息 */
    bzero(&mine, sizeof(mine));
    mine.sin_family = AF_INET;
    mine.sin_port = htons(atoi(argv[4]));
    if (inet_aton(argv[3], (struct in_addr *) &mine.sin_addr.s_addr) == 0) {
        perror(argv[3]);
        exit(errno);
    }

    /* 把自己的 IP 地址信息和端口与 socket 绑定 */
    if (bind(sockfd, (struct sockaddr *) &mine, sizeof(struct sockaddr)) ==
        -1) {
        perror(argv[3]);
        exit(errno);
    }

    /* 以自己特定的端口和IP连接服务器的特定端口 */
    if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {
        perror("Connect ");
        exit(errno);
    }

    /* 接收对方发过来的消息,最多接收 MAXBUF 个字节 */
    bzero(buffer, MAXBUF);
    recv(sockfd, buffer, sizeof(buffer), 0);
    printf("%s", buffer);
    sleep(10);
    /* 关闭连接 */
    close(sockfd);
    return 0;
}

编译程序用此命令:
引用:
gcc -Wall simple-bind.c


运行程序用此命令:
引用:
./a.out 127.0.0.1 22 127.0.0.1 3000


同时可以用下列netstat命令查看网络连接状态:
引用:
netstat -an|grep 3000


查看到如下信息:
引用:
tcp 0 0 127.0.0.1:3000 127.0.0.1:22 ESTABLISHED



与前面一份源代码相比,这里多了设置自己的IP地址和端口信息,所以编程过程变成了:
第1步:建立一个socket句柄,用socket()函数;
第2步:设定你要连接的服务器的IP地址和端口等信息;
第x步:设定你自己的IP地址和端口等信息与socket绑定,用bind()函数; #与前面相比就是多了这一个步骤
第3步:与服务器建立连接,用connect函数;
第4步:收发消息,用recv(sockfd,...)/send(sockfd,...)或者read(sockfd,...)/write(sockfd,...)都可以;
第5步:通讯结束后关闭连接,用close()函数即可,当然也有人用shutdown()函数。

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define MAXBUF 10
/************关于本文档********************************************
*filename: simple-readall.c
*purpose: 演示最基本的网络编程,循环读取服务器上发过来的内容,直到读完为止
*wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
*date time:2007-01-23 20:16:54
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
*********************************************************************/
int main(int argc, char **argv)
{
    int sockfd, ret;
    struct sockaddr_in dest, mine;
    char buffer[MAXBUF + 1];
    if (argc != 5) {
        printf
  ("参数格式错误!正确用法如下:\n\t\t%s 对方IP地址 对方端口 本机IP地址 本机端口\n\t比如:\t%s 127.0.0.1 80\n此程序用来以本机固定的端口从某个 IP 地址的服务器某个端口接收最多 MAXBUF 个字节的消息",
             argv[0], argv[0]);
        exit(0);
    }
    /* 创建一个 socket 用于 tcp 通信 */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Socket");
        exit(errno);
    }

    /* 初始化服务器端(对方)的地址和端口信息 */
    bzero(&dest, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_port = htons(atoi(argv[2]));
    if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0) {
        perror(argv[1]);
        exit(errno);
    }

    /* 初始化自己的地址和端口信息 */
    bzero(&mine, sizeof(mine));
    mine.sin_family = AF_INET;
    mine.sin_port = htons(atoi(argv[4]));
    if (inet_aton(argv[3], (struct in_addr *) &mine.sin_addr.s_addr) == 0) {
        perror(argv[3]);
        exit(errno);
    }

    /* 把自己的 IP 地址信息和端口与 socket 绑定 */
    if (bind(sockfd, (struct sockaddr *) &mine, sizeof(struct sockaddr)) ==
        -1) {
        perror(argv[3]);
        exit(errno);
    }

    /* 连接服务器 */
    if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) {
        perror("Connect ");
        exit(errno);
    }

    /* 接收对方发过来的消息,每次最多接收 MAXBUF 个字节,直到把对方发过来的所有消息接收完毕为止 */
    do {
        bzero(buffer, MAXBUF + 1);
        ret = recv(sockfd, buffer, MAXBUF, 0);
        printf("读到%d个字节,它们是:'%s'\n", ret, buffer);
    } while (ret == MAXBUF);

    /* 关闭连接 */
    close(sockfd);
    return 0;
}

编译程序使用如下命令:
引用:
gcc -Wall simple-readall.c


运行程序用如下命令:
引用:
./a.out 127.0.0.1 22 127.0.0.1 3000


此程序运行结果如下:
引用:
读到10个字节,它们是:'SSH-2.0-Op'
读到10个字节,它们是:'enSSH_4.3p'
读到10个字节,它们是:'2 Debian-5'
读到8个字节,它们是:'ubuntu1
'


注意:如果你运行时程序长久没有退出,请把程序的第一行:
引用:#define MAXBUF 10

稍微改一下,比如改成下面的:
引用:#define MAXBUF 9

再编译运行试试。
为什么?请继续看下一篇文章“设置非阻塞方式”。

zhoulifa 回复于:2007-02-04 13:00:49
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#define MAXBUF 10
/************关于本文档********************************************
*filename: simple-nonblock.c
*purpose: 演示最基本的网络编程,循环读取服务器上发过来的内容,直到读完为止
*wrote by: zhoulifa( zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
*date time:2007-01-23 20:46:54
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
*********************************************************************/
int main(int argc, char **argv)
{
    int sockfd, ret, rcvtm = 0;
    struct sockaddr_in dest, mine;
    char buffer[MAXBUF + 1];
    if (argc != 5) {
        printf
            ("参数格式错误!正确用法如下:\n\t\t%s 对方IP地址 对方端口 本机IP地址 本机端口\n\t比如:\t%s 127.0.0.1 80\n此程序用来以本机固定的端口从某个 IP 地址的服务器某个端口接收最多 MAXBUF 个字节的消息",


转载请标明出处:http://7798.org/technology/13494_6.html

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值