#include<stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define SERVPORT 3333
#define MAXDATASIZE 100 /*每次最大数据传输量 */
main(int argc, char *argv[]){
int sockfd, recvbytes;
char buf[MAXDATASIZE];
struct hostent *host;
struct sockaddr_in serv_addr;
if (argc < 2) {
fprintf(stderr,"Please enter the server's hostname!\n");
exit(1);
}
if((host=gethostbyname(argv[1]))==NULL) {
herror("gethostbyname出错!");
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
perror("socket创建出错!");
exit(1);
}
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(SERVPORT);
serv_addr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(serv_addr.sin_zero),8);
if (connect(sockfd, (struct sockaddr *)&serv_addr, \
sizeof(struct sockaddr)) == -1) {
perror("connect出错!");
exit(1);
}
if ((recvbytes=recv(sockfd, buf, MAXDATASIZE, 0)) ==-1) {
perror("recv出错!");
exit(1);
}
buf[recvbytes] = '\0';
printf("Received: %s",buf);
close(sockfd);
}
今天了解了一下socket编程。按照网上的例子写了个Client/Server的简单例子!
在写代码过程中,有几个问题很让我费解!
如上代码,是一个客户段程序,其中通过方法gethostbyname进行域名于IP的转换。返回一个hostend的结构体。如下:
struct hostent {
char *h_name; /* 主机的官方域名 */
char **h_aliases; /* 一个以NULL结尾的主机别名数组 */
int h_addrtype; /* 返回的地址类型,在Internet环境下为AF-INET */
int h_length; /* 地址的字节长度 */
char **h_addr_list; /* 一个以0结尾的数组,包含该主机的所有地址*/
};
#define h_addr h_addr_list[0] /*在h-addr-list中的第一个地址*/
sockaddr_in结构体:
struct sockaddr_in { short int sin_family; // Address family unsigned short int sin_port; // Port number struct in_addr sin_addr; // Internet address unsigned char sin_zero[8]; // Same size as struct sockaddr };
sockaddr结构体:
struct sockaddr { unsigned short sa_family; // address family, AF_xxx char sa_data[14]; // 14 bytes of protocol address };
in_addr结构体:
struct in_addr { unsigned long s_addr; // that’s a 32-bit long, or 4 bytes };
在填充sockaddr_in结构体时:serv_addr.sin_addr = *((struct in_addr *)host->h_addr);
sockaddr_in与sockaddr都是16个字节,只是sockaddr的表现形式更形象,对象化而已。而in_addr结构体就是一个long型
可以猜测h_addr_list是一个4字节网络字节序的in_addr,只是使用char*来表示,h_addr与struct in_addr其实形式是一样的。然后将host->h_addr强转成struct in_addr格式的指针,最后取值。(哈哈,这个就是C比Java强悍的地方,指针可真是一把双面刃).