2011-04-26 104 views
1

我刚开始学习socket编程,发现它很有趣。 目前,我正在服务器和客户端在同一台计算机上,因此我可以有IP地址作为环回地址,127.0.0.1和一切似乎工作正常!初学者的Socket编程C

但现在我正在考虑有两台电脑,做这件事.. 我有以下问题 - 1)说一台电脑是服务器,另一台是客户端。现在,如果服务器代码驻留在服务器计算机上并且客户端上的客户端代码是? 2)在我们为bind()提供ip地址的服务器代码中,它应该是我们可以通过ipconfig找到的系统的ip地址,或者它应该仍然是回送地址? 3)在客户端代码中,我猜目的地的IP地址应该是服务器计算机的IP地址? 4)最后也是最重要的事情,我如何连接两台计算机?

我附加了我开始使用的简单服务器和客户端消息传递代码。请指导我,我需要进行更改..

服务器代码

#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <string.h> 

#define MYPORT 3500 

int main() 
{ 
    int sockfd; 
    int clientfd; 
    int bytes_read; 
    char buf[100]; 
    int struct_size; 
    struct sockaddr_in my_addr; 
    struct sockaddr_in con_addr; 

    sockfd = socket(AF_INET, SOCK_STREAM, 0); 

    my_addr.sin_family = AF_INET; 
    my_addr.sin_port = htons(MYPORT); 
    my_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    my_addr.sin_zero[8]='\0'; 

    bind(sockfd, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)); 

    listen(sockfd,5); 

    struct_size = sizeof(con_addr); 
    clientfd = accept(sockfd, (struct sockaddr*)&con_addr, &struct_size); 

    bytes_read = read(clientfd, buf, 100); 
    buf[bytes_read] = '\0'; 
    printf("Message from client:%d is %s \n",clientfd, buf); 

    close(sockfd); 
    close(clientfd); 
} 

客户端代码

#include<sys/types.h> 
#include<sys/socket.h> 
#include<netinet/in.h> 
#include<fcntl.h> 
#include<string.h> 
#include<stdio.h> 

#define DESTPORT 3500 

int main() 
{ 

    struct sockaddr_in dest_addr; 

    int sockfd = socket(AF_INET,SOCK_STREAM,0); 

    dest_addr.sin_family = AF_INET; 
    dest_addr.sin_port = htons(DESTPORT); 
    dest_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    dest_addr.sin_zero[8]='\0'; 

    connect(sockfd,(struct sockaddr*)&dest_addr, sizeof(struct sockaddr)); 

    char msg[100]; 
    printf("Enter you message: "); 
    gets(&msg); 

    int w = write(sockfd, msg, strlen(msg)); 

    close(sockfd); 
    printf("Client Dying.....\n"); 

    return 0; 
} 

回答

1

服务器应该bind0.0.0.0(任何),除非你试图限制访问(在这种情况下,你应该真的使用防火墙,而不是端口绑定)。正确的方法实际上是:

struct addrinfo *ai, hints = { .ai_flags = AI_PASSIVE }; 
if (getaddrinfo(0, "1234", &hints, &ai)) goto error; 
int fd = socket(ai->ai_family, SOCK_STREAM, 0); 
bind(fd, ai->ai_addr, ai->ai_addrlen); 

当然,添加一些错误检查。将“1234”替换为您的端口号。

+0

解决我的情况只是我想要的方式..谢谢吨:-) 你可以建议一些很好的资源来了解有关现代套接字编程? – sachin11 2011-04-26 14:52:15

+0

对于'getaddrinfo','getnameinfo','socket','bind','''''''''''''''''''''''基本上是man页面(或POSIX文档,这里是:http://pubs.opengroup.org/onlinepubs/9699919799/functions/getaddrinfo.html) connect','listen','accept','sendto','recvfrom'和'select'就是您所需要的全部。您在较旧的示例和教程中看到的所有复杂性只是传统的包袱,并且不利于IPv6的支持和可移植性。 – 2011-04-26 14:55:58

+0

你为什么不在任何地方指定端口? – JeremyP 2011-04-26 15:08:45

0

127.0.0.1 localhost的是环回地址的机器你是目前。 如果您使用两个单独的框,您可能想要将其更改为客户端中的真实IP。

是的,客户端通常但不总是在服务器的另一个物理盒上。 如果您需要,您可以在omne方块上运行这两件作品

+0

谢谢先生..所以,我将客户端代码中的IP地址更改为服务器机器的IP地址..很好..但是,我应该如何处理服务器代码上的IP地址,这里是 my_addr .sin_addr.s_addr = inet_addr(“127.0.0.1”); – sachin11 2011-04-26 14:44:39

+1

你不应该手动捅[sin_addr.s_addr]等。这是90年代初期的一种不好的套接字编程,会给您带来很多麻烦,并且很难支持IPv6。看到我的答案为现代的方式来绑定套接字进行聆听。 – 2011-04-26 14:47:56

+1

@ R. +1请参阅:http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html – 2011-04-28 16:29:41

1

1)正确。

2)在服务器端,您可以绑定到0.0.0.0,这意味着“所有(IPv4)接口”。

3)是的,你是对的。

4)最常见的是通过以太网交换机(或交叉以太网电缆,但很难找到)。

+0

非常感谢你:-) – sachin11 2011-04-26 14:49:53

0

1)说一台电脑是服务器,另一台是客户端。现在,如果服务器代码驻留在服务器计算机上并且客户端上的客户端代码是?

我不认为我从正确的角度理解这一点...... lol.If您的客户端代码在服务器端,您如何分配任何内存或调用客户端计算机上的东西?

2)在我们为bind()提供ip地址的服务器代码中,它应该是我们可以通过ipconfig找到的系统的ip地址,或者它应该仍然是回送地址?

我们所拥有的手册页:

int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen); 

“bind()的addr所分配指定的地址文件描述符的sockfd简称插座addrlen中指定的大小,以字节为单位。传统上,这个操作被称为“为套接字分配一个名字” 在SOCK_STREAM套接字可能接收连接之前,通常需要使用bind()来分配一个本地地址(见accept(2 ))“。

就你而言,我想,你正在寻找127.0.0.1。简而言之,你谈到的地址更可能是你设置为server_addr结构的地址。

3)在客户端代码中,我猜目的地的IP地址应该是服务器计算机的IP地址吗?

是的。

4)最后也是最重要的是,如何连接两台计算机?

听起来像一个经典的聊天室应用程序。 据我所知(我是新手......),UDP(用户数据报协议)编程& API很值得一试。如果你想坚持TCP/IP,两台任意的计算机本质上不能连接到彼此,但都与服务器保持联系,服务器将成为他们之间的基石。

更重要的是,我看着一些插座手册页:

int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen); 

“的connect()系统调用连接用的sockfd到addr所指定的地址的文件描述符提到的插座的addrlen中参数指定addr的大小,addr中的地址格式取决于套接字sockfd的地址空间;有关更多详细信息,请参阅套接字(2)。

我认为这是以理论的方式完美地解释你的问题。