C语言实现TCP连接

最近学习网络连接的各种协议,决定先从TCP入手。

看了网上好多例子,然后自己动手用C做了一个TCP通信小工具。

本机是linux的,作为服务端;为了多学点东西,于是不辞辛苦装了台windows的虚拟机作为客户端;

简单总结了一下TCP的连接过程:

服务端:

  1. 初始化地址结构体
  2. 初始化套接字
  3. 绑定套接字和地址结构体
  4. 监听套接字
  5. 接受连接
  6. 开始自由通信
  7. 关闭套接字

客户端:

  1. 初始化服务器地址结构
  2. 初始化本机套接字
  3. 连接服务器
  4. 开始自由通信
  5. 关闭套接字

附上代码:

服务端(linux平台):

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
//线程所需参数
typedef struct _Args
{
    int socket_client;
}Args;
//接收信息的函数
void* GetMsg(void* arg);
int main(int argc,char *argv[])
{
    //服务器地址结构体
    struct sockaddr_in my_addr;
    //初始化服务器地址
    memset(&my_addr,0,sizeof(my_addr));
    my_addr.sin_family=AF_INET;
    my_addr.sin_addr.s_addr=INADDR_ANY;
    my_addr.sin_port=htons(1188);
    //套接字(个人理解:套接字就是协议的描述)
    int socket_server;
    //获得套接口描述符
    socket_server=socket(PF_INET,SOCK_STREAM,0);
    if(socket_server<=-1)
    {
        printf("socket error\n");
        return 1;
    }
    //绑定套接字与地址
    int result_bind = bind(socket_server,(struct sockaddr*)&my_addr,sizeof(struct sockaddr));
    if(result_bind<=-1)
    {
        printf("bind error\n");
        return 1;
    }
    //监听端口
    listen(socket_server,2);
    printf("waitind for connecting...\n");
    //储存client地址
    struct sockaddr_in client_addr;
    //接受连接
    int len_socket=sizeof(struct sockaddr);
    int socket_client=accept(socket_server,(struct sockaddr*)&client_addr,&len_socket);
    if(socket_client<=-1)
    {
        printf("accept error\n");
        return 1;
    }
    //打印连接信息
    printf("new client %s\n",inet_ntoa(client_addr.sin_addr) );
    //欢迎信息
    char* hello="hello friend!\n";
    send(socket_client,hello,strlen(hello),0);
    //线程接受信息所需参数
    Args args;
    args.socket_client=socket_client;
    //启动线程
    pthread_t thread;
    pthread_create(&thread,NULL,&GetMsg,(void*)&args);
    //发送信息
    char msg[101];
    memset(msg,‘\0‘,101*sizeof(char));
    while (strcmp(msg,"bye")!=0)
    {
        printf("send:\n\r");
        memset(msg,‘\0‘,100*sizeof(char));
        scanf("%s",msg);
        send(socket_client,msg,strlen(msg),0);
        printf("\n");
    }
    pthread_join(thread,NULL);
    close(socket_client);
    close(socket_server);
    return 0;
}
//接收信息
void* GetMsg(void* arg)
{
    int client_addr=((Args*)arg)->socket_client;
    char buffer[101];
    memset(buffer,‘\0‘,101*sizeof(char));
    while(strcmp(buffer,"bye")!=0)
    {
        memset(buffer,‘\0‘,100*sizeof(char));
        recv(client_addr,buffer,100,0);
        printf("\nrecv:\n%s\n\nsend:\n");
    }
}

客户端(windows平台):

#include <stdio.h> 
#include <winsock2.h> 
#include <string.h> 
#include <pthread.h> 
 
typedef struct _Arg 
{ 
    int socket_client; 
}Arg; 
void* GetMsg(void* args); 
 
 
int main(int argc, char *argv[]) 
{ 
    //初始化服务器地址 
    struct sockaddr_in server_addr; //服务器端网络地址结构体 
    memset(&server_addr,0,sizeof(struct sockaddr_in)); 
    server_addr.sin_family=AF_INET; //设置为IP通信 
    server_addr.sin_addr.s_addr=inet_addr("192.168.1.105");//服务器IP地址 
    server_addr.sin_port=htons(1188); //服务器端口号 
     
    //初始化本机套接字 
    WORD versionRequired=MAKEWORD(2,2); 
    WSADATA wsaData; 
    if (0!=WSAStartup(versionRequired,&wsaData))//协议库的版本信息 
    { 
        printf("ERROR:客户端的嵌套字打开失败!\n"); 
        return 1;//结束 
    } 
    SOCKET socket_client=socket(AF_INET,SOCK_STREAM,0); 
     
    //尝试连接 
    int result_connect=connect(socket_client,(struct sockaddr*)&server_addr,sizeof(struct sockaddr)); 
    if(result_connect<=-1) 
    { 
        printf("connect error\n"); 
        return 1; 
    } 
     
     
     
    //启动线程 
    Arg arg; 
    arg.socket_client=socket_client; 
    pthread_t thread; 
    pthread_create(&thread,NULL,GetMsg,(void*)&arg); 
     
     
    //发送 
    char msg[101]; 
    memset(msg,‘\0‘,101*sizeof(char)); 
    while(strcmp(msg,"bye")!=0) 
    { 
        printf("send:\n"); 
        memset(msg,‘\0‘,100*sizeof(char)); 
        scanf("%s",msg); 
        send(socket_client,msg,strlen(msg),0); 
        printf("\n"); 
    } 
     
    pthread_join(thread,NULL); 
    closesocket(socket_client); 
    WSACleanup(); 
     
    return 0; 
} 
 
void* GetMsg(void* args) 
{ 
    int socket_client=((Arg*)args)->socket_client; 
    char buffer[101]; 
    memset(buffer,‘\0‘,101*sizeof(char)); 
    while(strcmp(buffer,"bye")!=0) 
    { 
        memset(buffer,‘\0‘,100*sizeof(char)); 
        recv(socket_client,buffer,100,0); 
        printf("\nrecv:\n%s\n\nsend:\n",buffer); 
    } 
}

这只是一个简单的、不完整的、有BUG的小程序,还有很多没有做到位的地方,望高手指点

时间: 2024-10-18 03:57:15

C语言实现TCP连接的相关文章

利用tcpdump分析工具来验证tcp连接的建立和关闭过程

本文要求读者在阅读之前应该对TCP通过三次握手建立和关闭连接有一定的了解,本文并没有详细讲解三次握手,只是通过一个实例对三次握手进行了一下验证. tcp连接的建立和关闭想必大家都已经非常熟悉了!通过三次握手建立连接和通过三次或者四次(半关闭)握手来关闭连接!在这里,我想通过一个具体的实例程序,来分析一下这个过程! 首先说用到的工具吧,linux下的tcpdump命令,和自己用c语言写的一个服务器端和一个客户端程序.程序的代码如下: 头文件: 1 #include<stdio.h> 2 #inc

Linux C语言下TCP传结构体

1.废话不多说,本文介绍的是Linux下C语言实现TCP传递结构体数据: a.TCP Server一直在等待接收数据 b.TCP Client发送结构体数据 c.TCP Server接收数据并解析出来 2.结构体介绍: a.实际上要发送的结构体是: struct TCP_STRUCT_DATA{int m_cmd;//命令 可以用宏定义或者枚举区分不同的命令int m_data_len;//要发的数据的长度char *data;//要发的数据}DATA_SEND, *PDATA_SEND; b.

Qt模拟串口-tcp连接发送数据

上一节已经基本上完成了qt界面的基本布局,下面就是后台数据的发送和接收了, 前面说了,qt和uc/os 交互使用的方式是tcp 为啥要用tcp,而不使用别的呢, udp:按道理udp是最好的,不用连接,想发就发,不用管端口.但是,qt这个鬼,他封装的udp函数不支持服务器下发数据,也就是udp的服务器不能下发数据,只能接收. 串口:既然是串口通讯,为啥不直接用串口呢.c语言对串口的支持太差了, 很不好用,qt到还好,找个插件就能完成, 所以最后就采用了tcp的传输方式,既可以收发,也可以同时对应

如何在socket编程的Tcp连接中实现心跳协议

心跳包的发送,通常有两种技术 方法1:应用层自己实现的心跳包 由应用程序自己发送心跳包来检测连接是否正常,大致的方法是:服务器在一个 Timer事件中定时 向客户端发送一个短小精悍的数据包,然后启动一个低级别的线程,在该线程中不断检测客户端的回应, 如果在一定时间内没有收到客户端的回应,即认为客户端已经掉线:同样,如果客户端在一定时间内没 有收到服务器的心跳包,则认为连接不可用. 方法2:TCP的KeepAlive保活机制 因为要考虑到一个服务器通常会连接多个客户端,因此由用户在应用层自己实现心

TCP连接的状态详解以及故障排查

转载自CSDN博客:http://blog.csdn.net/hguisu/article/details/38700899 TCP状态 TCP状态迁移路线图 TCP连接建立三次握手 TCP连接的终止四次握手释放 同时打开 同时关闭 TCP通信中服务器处理客户端意外断开 Linux错误信息errno列表 我们通过了解TCP各个状态,可以排除和定位网络或系统故障时大有帮助.(总结网络上的内容) 1.TCP状态 了解TCP之前,先了解几个命令:   linux查看tcp的状态命令: 1).netst

解决不对称流量经过JUNIPER防火墙,tcp连接重置丢失问题

背景:公司网络增加一台JUNIPER防火墙,用于外网网关使用,其实配置上网配置很简单,配置完成后,外网连接测试也都正常,但在特殊的测试环境中会出现一种情况,该环境如图所示: 现象:当PC机的网关指定为防火墙的内网接口后(而不是核心交换机地址),当pc在telnet或者ssh连接10.10.2.*网段的服务器(网关在核心交换机上)等时,tcp连接均会在20s后重置.我的环境中其实存在一些问题的,就是流经防火墙的流量并不对称,其中pc→服务器的流量经过防火墙,而服务器→pc的流量不经过防火墙,造成的

TCP连接状态及TIME_WAIT

参考: TCP连接中的TIME_WAIT状态 - sunnydogzhou的专栏 - 博客频道 - CSDN.NET http://blog.csdn.net/sunnydogzhou/article/details/6572071 TCP连接状态详解及TIME_WAIT过多的解决方法_小强_新浪博客 http://blog.sina.com.cn/s/blog_8e5d24890102w9yi.html TCP协议三次握手连接四次握手断开和DOS攻击 - NowOrNever - 博客频道 -

TCP连接检测机制

采用TCP连接的C/S模式软件,连接的双方在连接空闲状态时,如果任意一方意外崩溃.当机.网线断开或路由器故障,另一方无法得知TCP连接已经失效,除非继续在此连接上发送数据导致错误返回.很多时候,这不是我们需要的.我们希望服务器端和客户端都能及时有效地检测到连接失效,然后优雅地完成一些清理工作并把错误报告给用户. 客户端采用如下步骤: 1, 连接 2, 拔掉网线 经过以上两步: 从上图中可以看到,此时服务端的连接依然存在. 所以,tcp只是数据的发送与接收,包括握手,断开以及rst,time_wa

服务器后台TCP连接存活问题

0. 背景 公司的服务器后台部署在某一个地方,接入的是用户的APP,而该地方的网络信号较差,导致了服务器后台在运行一段时间后用户无法接入,那边的同事反馈使用netstat查看系统,存在较多的TCP连接. 1. 问题分析 首先在公司内部测试服务器上部署,使用LoadRunner做压力测试,能正常运行,然后那边的同事反馈该地方信号较差.考虑到接入的问题,有可能接入进程的FD资源耗尽,导致accept失败.推论的依据是对于TCP连接来说,如果客户端那边由于一些异常情况导致断网而未能向服务器发起FIN关