博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
浅谈套接字编程—TCP
阅读量:4134 次
发布时间:2019-05-25

本文共 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/

你可能感兴趣的文章
java多线程环境单例模式实现详解
查看>>
将一个数插入到有序的数列中,插入后的数列仍然有序
查看>>
在有序的数列中查找某数,若该数在此数列中,则输出它所在的位置,否则输出no found
查看>>
万年历
查看>>
作为码农你希望面试官当场指出你错误么?有面试官这样遭到投诉!
查看>>
好多程序员都认为写ppt是很虚的技能,可事实真的是这样么?
查看>>
如果按照代码行数发薪水会怎样?码农:我能刷到公司破产!
查看>>
程序员失误造成服务停用3小时,只得到半月辞退补偿,发帖喊冤
查看>>
码农:很多人称我“技术”,感觉这是不尊重!纠正无果后果断辞职
查看>>
php程序员看过来,这老外是在吐糟你吗?看看你中了几点!
查看>>
为什么说程序员是“培训班出来的”就是鄙视呢?
查看>>
码农吐糟同事:写代码低调点不行么?空格回车键与你有仇吗?
查看>>
阿里p8程序员四年提交6000次代码的确有功,但一次错误让人唏嘘!
查看>>
一道技术问题引起的遐想,最后得出结论技术的本质是多么的朴实!
查看>>
985硕士:非科班自学编程感觉还不如培训班出来的,硕士白读了?
查看>>
你准备写代码到多少岁?程序员们是这么回答的!
查看>>
码农:和产品对一天需求,产品经理的需求是对完了,可我代码呢?
查看>>
程序员过年回家该怎么给亲戚朋友解释自己的职业?
查看>>
技术架构师的日常工作是什么?网友:搭框架,写公共方法?
查看>>
第四章 微信飞机大战
查看>>