网络程序设计核心——socket接收发送信息(套接字)
server端——调用socket——bind函数——Client server——accept函数——Client
Client端——调用socket——connect函数——Server主机——IP端口号
#include<sys/types.h>
#include<sys/socket.h>
int socket(int domain,int type,int protocol);
/*
domain 协议簇设置为AF_INET(TCP/IP 协议簇),AF_UNIX(域协议簇),AF_ISO(协议簇);
type 套接字类型(SOCK_STREAM流套,SOCK_DGRAM数据报套,SOCK_RAM原始套接字);
protocol可设置为0.
*/
int connect(int sockfd,struct sockaddr *servaddr,int addren);
/*sockfd返回的描述符,servaddr服务器地址、传输端口号及地址类型,addren地址长度*/
// Linux系统4个库函数的字节顺序转换:
#include<netinet/in.h>
unsigned long int htonl(unsigned long int hostlong);
unsigned short int htons(unsigned short int hostshort);
unsigned long int ntohl(unsigned long int netlong);
unsigned short int ntohs(unsigned short int netshort);
int bind(int sockfd,struct sockaddr *my_addr,int addrlen);
/*描述符,指针包含名称端口与IP地址,地址长度*/
int listen(int sockfd,int backlog);//backlog指定连接请求队列最大长度,成功返回0,否则-1.
int accept(int sockfd,struct sockaddr *addr,int *addrlen);
/*描述符,套接字地址结构指针,长度,若对客户进程地址不感兴趣可将addr与addrlen设为NULL*/
int read(int fd,char *buf,int len); //buf是应用的发送缓冲区 成功返回字节数,0位关闭写管道,-1出错
int write(int fd,char *buf,int len); //buf是接收缓冲区
int rect(int sockfd,void *buf,int len,int flags); //与read相似 增加了读操作的控制
int send(int sockfd,void *buf,int len,int flags); //与write相似
#include<unistd.h>
int close(int sockfd); //成功返回0,失败返回-1,参考C语言中文网
//TCP套接字描述符
int sock_fd=socket(AF_INET,SOCK_STREAM,0);//成功返回描述符,调用失败则返回-1,下面的if语句用于判断。
if(sock_fd<0)
{
perror("socket creating error");
exit(1); //进程退出会有一个返回值,1表示异常退出,0表示正常退出。
}
//套接字地址:
struct sockaddr
{
unsigned short sa_family; //sa_family为协议簇地址类型
char sa_date[14]; //14字节的协议地址,sa_data存储具体地址内容
};
//每种协议簇定义自己的协议地址类型
struct in_addr
{
_u32 s_addr; //unsigned long 32比特的IP地址
};
struct socketaddr_in
{
short in sin_family; //地址类型
unsigned short int sin_port; //端口号
struct in_addr sin_addr; //Internet地址
unsigned char _pad[_SOCK_SIZE-sizeof(short int)-sizeof(unsigned short int)-sizeof(struct in_addr)];//填充比特
};//编写TCP与UDP代码时,通常使用struct sockaddr_in结构来赋值
//connect()函数用法:
struct socketaddr_in serv_addr;
int ret,sock_fd;
bzero(&serv_addr,sizeof(struct,sockaddr_in)); //套接字清零,包含'\0'。2008标准已没有该函数,可用memset()代替,是对结构体与数组清零最快方法。
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(SERVER_PORT);
ret=inet_aton("127.0.0.1",&serv_addr.sin_addr); //参考arpa/inet.h 将一个字符串IP地址转换为一个32位的网络序列IP地址,即带“点”的地址。
if(ret<0)
{
perror("convert IP address error"); //转换IP地址错误
exit(1);
}
ret=connect(sock_fd,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr_in));
if(ret<0)
{
perror("connect to server error");
exit(1);
}
//bind()函数用法:
struct sockaddr_in serv_addr;
bzero(&serv_addr,sizeof(struct sockaddr_in));
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(SERVER_PORT);
serv_addr.sin_addr.s_addr=htonl(INADDR_ANY); //INADDR_ANY指任何网络设备接口
ret=(bind(sock_fd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
if(ret<0)
{
perror("bind to SERVER_PORT error");
exit(1);
}
/*
实现由服务器向客户端发送字符串“Hello World!”
服务器代码如下:
*/
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/type.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/wait.h>
#define MYPORT 4050
#define BACKLOG 10
int main()
{
int sockfd,new_fd;
struct sockaddr_in my_addr; //有问题吧?
struct sockaddr_in their_addr;
int sin_size;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket");
exit(1);
}
else
{
printf("socket created successfully!\n");
}
my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(MYPORT);
my_addr.sin_addr.s_addr=INADDR_ANY;
bzero(&(my_addr.sin_zero),8);
if(bind(sockfd,(struct sockaddr*)&my_addr,sizeof(structaddr))==-1)
{
perror("bindB");
exit(1);
}
else
printf("address binded sucessfully!\n");
if(listen(sockfd,BACKLOG)==-1)
{
perror("listen");
exit(1);
}
else
printf("start listening the clients' connect request ……\n");
while(1)
{
sin_size=sizeof(struct sockaddr_in);
if((new_fd=accept(sockfd,(struct sockaddr*)&their_addr,&sin_size))==-1)
{
perror("accept");
exit(1);
}
else
printf("server.got connection from %s\n",inet_ntoa(their_addr.sin_addr));
if(!fork())
if(send(new_fd,"Hello World!\n",14,0)==-1)
{
perror("send");
close(new_fd);
exit(0);
}
close(new_fd);
}
while(waitpid(-1,NULL,WNOHANG)>0);
}
/*
客户端程序
*/
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/type.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/wait.h>
#define MAXDATASIZE 100
int main(int argc.char **argv)
{
int sockfd,numbytes,servport;
struct sockaddr in servaddr;
char buf[[MAXDATESIZE];
if(argc !=3)
{
fprintf(stderr,"usage:hellocli <server's ip address> <server's port>");
exit(1);
}
sockfd=socket(AF_INET,SOCK_STREAM,0);
bzero(&servaddr,sizeof(struct sockaddr_in));
servaddr.sin_family=AF_INET;
servaddr.sin_port=htons(atoi(argv[2]));
inet_aton(argv[1],&servaddr.sin_addr);
connect(sockfd,(struct sockaddr*)&servaddr,sizeof(struct sockaddr));
if(numbytes=recv(sockfd,buff,MAXDATESIZE,0))==-1)
{
perror("recv");
exit(1);
}
buf[numbytes]='\0';
printf("Receive from server %s:\n %s",argv[1],buf);
printf("totally %d bytes received\n\n",numbytes);
close(sockfd);
printf("……local socket closed\n");
return 0;
}
参考:
SOCKET.H 头文件: http://pubs.opengroup.org/onlinepubs/7908799/xns/syssocket.h.html
NETINET/IN.H 头文件: http://pubs.opengroup.org/onlinepubs/7908799/xns/netinetin.h.html
ARPA/INET.H 头文件 http://pubs.opengroup.org/onlinepubs/7908799/xns/arpainet.h.html
C语言中文网:http://c.biancheng.net/cpp/html/229.html
可清零的初始化函数:memset(void *s,int ch,size_t n);