本文共 4901 字,大约阅读时间需要 16 分钟。
我们学习编程,一般学习过程为先看语法,写出我们的第一个Hello World程序,然后进一步学习数据及数据结构,最后我们可能想应用方面学习。下面我就来谈谈我对网络编程中的TCP套接字编程的知识。
TCP提供可靠的连接的通信方式:一般编程步骤见下图1,
图1
下面先看个客户端与服务器的例子
/*客户端*/
#include <stdio.h>
#include <sys/socket.h> #include <netinet/in.h> #include <stdlib.h> #include <string.h> int main(int argc,char **argv) { int sockfd,n; struct sockaddr_in servaddr,cliaddr; char sendline[1000]; char recvline[1000]; if(argc != 2) { printf("usage:client <IP address>\n"); exit(1); } sockfd = socket(AF_INET,SOCK_STREAM,0); bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = inet_addr(argv[1]); servaddr.sin_port = htons(32000); connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr)); while(fgets(sendline,1000,stdin) != NULL) { sendto(sockfd,sendline,strlen(sendline),0,(struct sockaddr*)&servaddr,sizeof(servaddr)); n = recvfrom(sockfd,recvline,1000,0,NULL,NULL); recvline[n] = '\0'; fputs(recvline,stdout); } close(sockfd); return 0; }/*服务器*/
#include <stdlib.h>
#include <stdio.h> #include <errno.h> #include <string.h> #include <netdb.h> #include <sys/types.h> #include <netinet/in.h> #include <sys/socket.h> int main(int argc, char *argv[]) { int sockfd,new_fd; struct sockaddr_in server_addr; struct sockaddr_in client_addr; int sin_size; int nbytes; char buffer[1024]; /* 服务器端开始建立sockfd描述符 */ if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) // AF_INET:IPV4;SOCK_STREAM:TCP { fprintf(stderr,"Socket error:%s\n\a",strerror(errno)); exit(1); } /* 服务器端填充 sockaddr结构 */ bzero(&server_addr,sizeof(struct sockaddr_in)); // 初始化,置0 server_addr.sin_family=AF_INET; // Internet IPV4 server_addr.sin_addr.s_addr=htonl(INADDR_ANY); // (将本机器上的long数据转化为网络上的long数据)和任何主机通信 //INADDR_ANY 表示可以接收任意IP地址的数据,即绑定到所有的IP //server_addr.sin_addr.s_addr=inet_addr("127.0.0.1"); //用于绑定到一个固定IP,inet_addr用于把数字加格式的ip转化为整形ip server_addr.sin_port=htons(32000); // (将本机器上的short数据转化为网络上的short数据)端口号 /* 捆绑sockfd描述符到IP地址 */ if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1) { fprintf(stderr,"Bind error:%s\n\a",strerror(errno)); exit(1); } /* 设置允许连接的最大客户端数 */ if(listen(sockfd,5)==-1) { fprintf(stderr,"Listen error:%s\n\a",strerror(errno)); exit(1); } while(1) { /* 服务器阻塞,直到客户程序建立连接 */ sin_size=sizeof(struct sockaddr_in); printf("accepting!\n"); if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size))==-1) { fprintf(stderr,"Accept error:%s\n\a",strerror(errno)); exit(1); } fprintf(stderr,"Server get connection from %s\n",inet_ntoa(client_addr.sin_addr)); // 将网络地址转换成.字符串 if((nbytes=read(new_fd,buffer,1024))==-1) { fprintf(stderr,"Read Error:%s\n",strerror(errno)); exit(1); } buffer[nbytes]='\0'; printf("Server received %s\n",buffer); /* 这个通讯已经结束 */ close(new_fd); /* 循环下一个 */ } /* 结束通讯 */ close(sockfd); exit(0); }例子是照步骤编的,其实TCP套接字编程很容易,只要照它步骤来,首先看客户端:
sockfd = socket(AF_INET,SOCK_STREAM,0);
创建套接字,
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(argv[1]);servaddr.sin_port = htons(32000);
初始化套接字类型,地址,端口号
connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr));
请求建立连接
while(fgets(sendline,1000,stdin) != NULL)
{ sendto(sockfd,sendline,strlen(sendline),0,(struct sockaddr*)&servaddr,sizeof(servaddr)); n = recvfrom(sockfd,recvline,1000,0,NULL,NULL); recvline[n] = '\0'; fputs(recvline,stdout); }收发数据
close(sockfd);
关闭套接字,断开连接
再看服务器:
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) // AF_INET:IPV4;SOCK_STREAM:TCP
{ fprintf(stderr,"Socket error:%s\n\a",strerror(errno)); exit(1); } /* 服务器端填充 sockaddr结构 */ bzero(&server_addr,sizeof(struct sockaddr_in)); // 初始化,置0 server_addr.sin_family=AF_INET; // Internet IPV4 server_addr.sin_addr.s_addr=htonl(INADDR_ANY); // (将本机器上的long数据转化为网络上的long数据)和任何主机通信 //INADDR_ANY 表示可以接收任意IP地址的数据,即绑定到所有的IP //server_addr.sin_addr.s_addr=inet_addr("127.0.0.1"); //用于绑定到一个固定IP,inet_addr用于把数字加格式的ip转化为整形ip server_addr.sin_port=htons(32000); // (将本机器上的short数据转化为网络上的short数据)端口号创建套接字,并初始化套接字类型与端口号等,这里注意:端口号与客户端的端口号一致,否则无法连接。
if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
{ fprintf(stderr,"Bind error:%s\n\a",strerror(errno)); exit(1); }捆绑sockfd描述符到IP地址,
if(listen(sockfd,5)==-1)
{ fprintf(stderr,"Listen error:%s\n\a",strerror(errno)); exit(1); }设置允许连接的最大客户端数5
while(1)
{ /* 服务器阻塞,直到客户程序建立连接 */ sin_size=sizeof(struct sockaddr_in); printf("accepting!\n"); if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size))==-1) { fprintf(stderr,"Accept error:%s\n\a",strerror(errno)); exit(1); } fprintf(stderr,"Server get connection from %s\n",inet_ntoa(client_addr.sin_addr)); // 将网络地址转换成.字符串 if((nbytes=read(new_fd,buffer,1024))==-1) { fprintf(stderr,"Read Error:%s\n",strerror(errno)); exit(1); } buffer[nbytes]='\0'; printf("Server received %s\n",buffer); /* 这个通讯已经结束 */ close(new_fd); /* 循环下一个 */ }收发数据
close(sockfd);
关闭连接。
其实只要掌握以下几点就可以了:
1.客户端,服务器端口号要一致;
2.服务器 端accept连接后生成一个新的sockfd,最后先关这个新的sockfd,再关之前创建的sockfd。
我认为就这些就可以啦。
转载地址:http://amsvi.baihongyu.com/