网络编程学习笔记
一 常用数据结构
在设计网络程序之前,需要了解两个重要的数据类型sockaddr和sockaddr_in.两个结构都是
用来保存socket信息的,如IP地址,通信端口等,它们的具体定义如下所示:
struct sockaddr{
unsigned short sa_family;//sa_family一般为AF_INET,代表Internet(TCP/IP)地址族
char sa_data[14];//sa_data则包含该socket的IP地址和端口号
};
struct sockaddr_in{
short int sin_family;//地址族
unsigned short int sin_port;//端口号
struct in_addr sin_addr;//IP地址
unsigned char sin_zero[8];//填充0以保持与struct sockaddr同样大小
};
其中sin_zero用来将sockaddr_in结构填充到与struct sockaddr同样的长度,可以用bzeor()
函数将其置零。这样即使socket()想要使用struct sockaddr结构,仍然可以使用struct
sockaddr_in进行定义,只要用bzero()将sockaddr_in.sin_zero置为零就可以转换了。
二 TCP网络编程常用的函数及功能
bind:将socket与本机上的一个端口绑定,随后就可以在该端口监听服务请求
connect:面向连接的客户程序使用connect函数来配置socket,并与远端服务器建立一个TCP连
接
listen:listen函数使socket处于被动的监听模式,并为该socket建立一个输入数据队列,将
到达的服务请求保存在此队列中,直到程序处理它们。
accept:accept函数让服务接受客户的连接请求
close:停止在该socket上的任何数据操作
send:数据发送函数
recv:数据结构函数。
示例程序:
server.c
----------------------
#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>
#define SERVPORT 3333
#define BACKLOG 10
int main()
{
int sockfd,client_fd;
struct sockaddr_in my_addr;
struct sockaddr_in remote_addr;
int sin_size;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
perror("socket created failed!");exit(1);
}
my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(SERVPORT);
my_addr.sin_addr.s_addr=INADDR_ANY;
bzero(&(my_addr.sin_zero),8);
if(bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr))==-1)
{
perror("bind error!");
exit(1);
}
if(listen(sockfd,BACKLOG)==-1){
perror("listen error!");
exit(1);
}
while(1){
sin_size=sizeof(struct sockaddr_in);
if((client_fd=accept(sockfd,(struct sockaddr*)&remote_addr,&sin_size))==-1)
{
perror("accept error!");
continue;
}
printf("receive a connection from: %s/n",inet_ntoa(remote_addr.sin_addr));
if(!fork()){
if(send(client_fd,"have connected /n",26,0)==-1)
perror("send error!");
close(client_fd);
exit(0);
}
close(client_fd);
}
}
-----------
client.c
-----------------------
#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
int 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){
perror("gethostbyname error!");
exit(1);
}
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){
perror("socket created error!");
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 error!");
exit(1);
}
if((recvbytes=recv(sockfd,buf,MAXDATASIZE,0))==-1){
perror("connected error!");
exit(1);
}
printf("received: %s",buf);
close(sockfd);
}