转自:http://blog.csdn.net/piaojun_pj/article/details/5920888
转自:http://blog.sina.com.cn/s/blog_6151984a0100etj1.html
发现这两篇博文写得挺详细的,我没有运行,目测应该是没问题的。!!
---------------------------------------邪恶的割割-------------------------------------------------
套接字是一种进程间的通信的方法,不同于以往介绍的进程间通信方法的是,它并不局限于同一台计算机的资源,例如文件系统空间,共享内存或者消息队列。套接字可以认为是对管道概念的扩展——一台机器上的进程可以使用套接字与另一台机器上的进程通信。因此客户与服务器可以分散在网络中。同一台机器上的进程间也可以用套接字通信。套接字是一种通信机制,客户/服务器系统既可以在本地单机上运行,也可以在网络中运行。套接字与管道的区别:它明确区分客户与服务器,可以实现将多个客户连接到一个服务器。
---------------------------------------------------------------------------------------------------
sockaddr结构体
sockaddr的缺陷:sa_data把目标地址和端口信息混在一起了
struct sockaddr { char sa_data[14]; }; |
sa_family是通信类型,最常用的值是 "AF_INET" sa_data14字节,包含套接字中的目标地址和端口信息 |
由于sockaddr把地址和端口信息都封装在sd_data[14]中,我们不了解该怎么赋值,所以就有了sockaddr_in这个结构体:
sockaddr_in结构体解决了sockaddr的缺陷,把port和addr 分开储存在两个变量中
struct sockaddr_in { short int sin_family; unsigned
} |
我们可以看见,sin_port(short)是2字节,sin_addr(long)是4字节,sin_zero[]是8字节,总共是14字节,这个就是上面sa_data[]的具体分布情况,所以sockaddr与sockaddr_in是可以相互转换的数据结构。
因为要设置sin_zero为0初始化。所以这个结构体的初始化过程为:
-
memset(&my_addr,0,sizeof(my_addr)); //数据初始化--清零 -
my_addr.sin_family=AF_INET; //设置为IP通信 -
my_addr.sin_addr.s_addr=INADDR_ANY;//服务器IP地址--允许连接到所有本地地址上 -
my_addr.sin_port=htons(8000); //服务器端口号
好了,理解了上面这两个结构体(也可以所三个,哈有个in_addr设置地址用的)就可以开始看代码啦!
----------------------------------------------------------------------------------------------------------
TCP协议:
服务器端:tcp_server.c
- #include
- #include
- #include
- #include
- #include
-
- int
main(int argc, char *argv[]) - {
-
int server_sockfd;//服务器端套接字 -
int client_sockfd;//客户端套接字 -
int len; -
struct sockaddr_in my_addr; //服务器网络地址结构体 -
struct sockaddr_in remote_addr; //客户端网络地址结构体 -
int sin_size; -
char buf[BUFSIZ]; //数据传送的缓冲区 -
memset(&my_addr,0,sizeof(my_addr)); //数据初始化--清零 -
my_addr.sin_family=AF_INET; //设置为IP通信 -
my_addr.sin_addr.s_addr=INADDR_ANY;//服务器IP地址--允许连接到所有本地地址上 -
my_addr.sin_port=htons(8000); //服务器端口号 -
-
-
if((server_sockfd=socket(PF_INET,SOCK_STREAM,0))<0) -
{ -
perror("socket"); -
return 1; -
} -
-
-
if (bind(server_sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))<0) -
{ -
perror("bind"); -
return 1; -
} -
-
-
listen(server_sockfd,5); -
-
sin_size=sizeof(struct sockaddr_in); -
-
-
if((client_sockfd=accept(server_sockfd,(struct sockaddr *)&remote_addr,&sin_size))<0) -
{ -
perror("accept"); -
return 1; -
} -
printf("accept client %s/n",inet_ntoa(remote_addr.sin_addr)); -
len=send(client_sockfd,"Welcome to my server/n",21,0);//发送欢迎信息 -
-
-
while((len=recv(client_sockfd,buf,BUFSIZ,0))>0)) -
{ -
buf[len]='/0'; -
printf("%s/n",buf); -
if(send(client_sockfd,buf,len,0)<0) -
{ -
perror("write"); -
return 1; -
} -
} -
close(client_sockfd); -
close(server_sockfd); -
return 0; - }
TCP协议:
客户端:tcp_client.c
- #include
- #include
- #include
- #include
- #include
-
- int
main(int argc, char *argv[]) - {
-
int client_sockfd; -
int len; -
struct sockaddr_in remote_addr; //服务器端网络地址结构体 -
char buf[BUFSIZ]; //数据传送的缓冲区 -
memset(&remote_addr,0,sizeof(remote_addr)); //数据初始化--清零 -
remote_addr.sin_family=AF_INET; //设置为IP通信 -
remote_addr.sin_addr.s_addr=inet_addr("127.0.0.1");//服务器IP地址 -
remote_addr.sin_port=htons(8000); //服务器端口号 -
-
-
if((client_sockfd=socket(PF_INET,SOCK_STREAM,0))<0) -
{ -
perror("socket"); -
return 1; -
} -
-
-
if(connect(client_sockfd,(struct sockaddr *)&remote_addr,sizeof(struct sockaddr))<0) -
{ -
perror("connect"); -
return 1; -
} -
printf("connected to server/n"); -
len=recv(client_sockfd,buf,BUFSIZ,0);//接收服务器端信息 -
buf[len]='/0'; -
printf("%s",buf); //打印服务器端信息 -
-
-
while(1) -
{ -
printf("Enter string to send:"); -
scanf("%s",buf); -
if(!strcmp(buf,"quit") -
break; -
len=send(client_sockfd,buf,strlen(buf),0); -
len=recv(client_sockfd,buf,BUFSIZ,0); -
buf[len]='/0'; -
printf("received:%s/n",buf); -
} -
close(client_sockfd);//关闭套接字 -
return 0; - }
UDP协议:
服务器端:udp_server.c
- #include
- #include
- #include
- #include
- #include
-
- int
main(int argc, char *argv[]) - {
-
int server_sockfd; -
int len; -
struct sockaddr_in my_addr; //服务器网络地址结构体 -
struct sockaddr_in remote_addr; //客户端网络地址结构体 -
int sin_size; -
char buf[BUFSIZ]; //数据传送的缓冲区 -
memset(&my_addr,0,sizeof(my_addr)); //数据初始化--清零 -
my_addr.sin_family=AF_INET; //设置为IP通信 -
my_addr.sin_addr.s_addr=INADDR_ANY;//服务器IP地址--允许连接到所有本地地址上 -
my_addr.sin_port=htons(8000); //服务器端口号 -
-
-
if((server_sockfd=socket(PF_INET,SOCK_DGRAM,0))<0) -
{ -
perror("socket"); -
return 1; -
} -
-
-
if (bind(server_sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))<0) -
{ -
perror("bind"); -
return 1; -
} -
sin_size=sizeof(struct sockaddr_in); -
printf("waiting for a packet.../n"); -
-
-
if((len=recvfrom(server_sockfd,buf,BUFSIZ,0,(struct sockaddr *)&remote_addr,&sin_size))<0) -
{ -
perror("recvfrom"); -
return 1; -
} -
printf("received packet from %s:/n",inet_ntoa(remote_addr.sin_addr)); -
buf[len]='/0'; -
printf("contents: %s/n",buf); -
close(server_sockfd); -
return 0; - }
客户端:udp_client.c
- #include
- #include
- #include
- #include
- #include
-
- int
main(int argc, char *argv[]) - {
-
int client_sockfd; -
int len; -
struct sockaddr_in remote_addr; //服务器端网络地址结构体 -
int sin_size; -
char buf[BUFSIZ]; //数据传送的缓冲区 -
memset(&remote_addr,0,sizeof(remote_addr)); //数据初始化--清零 -
remote_addr.sin_family=AF_INET; //设置为IP通信 -
remote_addr.sin_addr.s_addr=inet_addr("127.0.0.1");//服务器IP地址 -
remote_addr.sin_port=htons(8000); //服务器端口号 -
-
-
if((client_sockfd=socket(PF_INET,SOCK_DGRAM,0))<0) -
{ -
perror("socket"); -
return 1; -
} -
strcpy(buf,"This is a test message"); -
printf("sending: '%s'/n",buf); -
sin_size=sizeof(struct sockaddr_in); -
-
-
if((len=sendto(client_sockfd,buf,strlen(buf),0,(struct sockaddr *)&remote_addr,sizeof(struct sockaddr)))<0) -
{ -
perror("recvfrom"); -
return 1; -
} -
close(client_sockfd); -
return 0; - }