tcp网络编程小结(一)

tcp/ip是当前网络通信方式最常见的一种通信协议族。我们最常听说ip、端口号、域名。
现在我们就来讲一讲基础通信是如何实现的。
编程主通过socket套接字实现的,使用下面两个结构体,sockaddr,sockaddr_in。这两个是等价的。

struct sockaddr
{
/*地址族,就是一些协议类型的集合*/
unsigned short sa_family;
/*14 字节的协议地址,包含该 socket 的 IP 地址和端口号*/
char sa_data[14];
};
struct sockaddr_in
{
short int sa_family; /*地址族*/
unsigned short int sin_port; /*端口号*/
struct in_addr sin_addr; /*IP 地址*/
/*全填 0,保持与 struct sockaddr 同样大小*/
unsigned char sin_zero[8];
}
套接字类型
流式 socket(SOCK_STREAM)
流式套接字提供可靠的、面向连接的通信流;它使用 TCP 协议,从而保证
了数据传输的正确性和顺序性。
数据报 socket(SOCK_DGRAM)
数据报套接字定义了一种无连接的服务,数据通过相互独立的报文进行传输,
是无序的,并且不保证是可靠、无差错的。它使用的数据报协议是 UDP。

sa_family的范围
AF_INET: IPv4 协议
AF_INET6:IPv6 协议
AF_LOCAL: UNIX 域协议
这里我们先讲tcp,后来再说udp.

tcp server端

	#include <stdio.h>  
    #include <stdlib.h>  
    #include <string.h>                         
    #include <unistd.h>  
    #include <sys/socket.h>  
    #include <netinet/in.h>  
    #include <arpa/inet.h>                      
    #include <pthread.h> 
	
	pthread_mutex_t mutex;  

	int DataCmp(char *des,char *src,int num)
	{
		int i;

		for(i=0;i<num;i++)
		{
			if(*(des+i)!=*(src+i))
				break;
		}
		if(i==num)
			return 1;
		else
			return 0;
	}
    void *client_process(void *arg)  
    {  
        int recv_len = 0;  
        char recv_buf[1024] = "";   // 接收缓冲区  
        int connfd = *(int *)arg; // 传过来的已连接套接字  
        char send_buf[1024] = ""; 
        // 解锁,pthread_mutex_lock()唤醒,不阻塞  
        pthread_mutex_unlock(&mutex);   
          
        // 接收数据  
        while((recv_len = recv(connfd, recv_buf, sizeof(recv_buf), 0)) > 0)  
        {  
         
      		printf("recv_buf: %s\n", recv_buf); // 打印数据 
			if(DataCmp((&recv_buf[4]),"10",2)==1)
			{	
				sprintf(send_buf,"%s","00111000001");
				send(connfd, send_buf,strlen(send_buf), 0); // 给客户端回数据  
			}
			if(DataCmp((&recv_buf[4]),"05",2)==1)
			{	
				sprintf(send_buf,"%s","0010050000");
				send(connfd, send_buf,strlen(send_buf), 0); // 给客户端回数据  
			}
        }  
          
        printf("client closed!\n");  
        close(connfd);  //关闭已连接套接字  
          
        return  NULL;  
    }  
      
 
    int main(int argc, char *argv[])  
    {  
        int sockfd = 0;             // 套接字  
        int connfd = 0;  
        int err_log = 0;  
        struct sockaddr_in my_addr; // 服务器地址结构体  
        unsigned short port = 8080; // 监听端口  
        pthread_t thread_id;  
          
        pthread_mutex_init(&mutex, NULL); // 初始化互斥锁,互斥锁默认是打开的  
          
        printf("TCP Server Started at port %d!\n", port);  
          
        sockfd = socket(AF_INET, SOCK_STREAM, 0);   // 创建TCP套接字  
        if(sockfd < 0)  
        {  
            perror("socket error");  
            exit(-1);  
        }  
          
        bzero(&my_addr, sizeof(my_addr));      // 初始化服务器地址  
        my_addr.sin_family = AF_INET;  
        my_addr.sin_port   = htons(port);  
        my_addr.sin_addr.s_addr = htonl(INADDR_ANY);  
          
          
        printf("Binding server to port %d\n", port);  
          
        // 绑定  
        err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));  
        if(err_log != 0)  
        {  
            perror("bind");  
            close(sockfd);        
            exit(-1);  
        }  
          
        
        err_log = listen(sockfd, 10);  
        if( err_log != 0)  
        {  
            perror("listen");  
            close(sockfd);        
            exit(-1);  
        }  
          
        printf("Waiting client...\n");  
          
        while(1)  
        {  
            char cli_ip[INET_ADDRSTRLEN] = "";     // 用于保存客户端IP地址  
            struct sockaddr_in client_addr;        // 用于保存客户端地址  
            socklen_t cliaddr_len = sizeof(client_addr);    
              
       
            pthread_mutex_lock(&mutex);   
              
            //获得一个已经建立的连接     
            connfd = accept(sockfd, (struct sockaddr*)&client_addr, &cliaddr_len);                                
            if(connfd < 0)  
            {  
                perror("accept this time");  
                continue;  
            }  
              
            // 打印客户端的 ip 和端口  
            inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN);  
            printf("----------------------------------------------\n");  
            printf("client ip=%s,port=%d\n", cli_ip,ntohs(client_addr.sin_port));  
              
            if(connfd > 0)  
            {  
                //给回调函数传的参数,&connfd,地址传递  
                pthread_create(&thread_id, NULL, (void *)client_process, (void *)&connfd);  //创建线程  
                pthread_detach(thread_id); // 线程分离,结束时自动回收资源  
            }  
        }  
        close(sockfd);  
          
        return 0;  
    } 

tcp 客户端

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
int sock_fd;
#define PORT 65534
void test(void *arg)
{
	while(1)
	{
    int connfd = *(int *)arg; // 传过来的已连接套接字  
 
     send(connfd, "123",3, 0);
	 sleep(2);
	}
}
int main(int argc,char argv[])
{
  	struct sockaddr_in server_addr;
    pthread_t id1;
  	if((sock_fd=socket(AF_INET,SOCK_STREAM,0))==-1)
  	{
 		printf("socket create fail\r\n");
 		exit(1);
    }
    server_addr.sin_family=AF_INET;
    server_addr.sin_port=htons(PORT );
    server_addr.sin_addr.s_addr=inet_addr("139.196.34.130");//根据自己的自行修改,随便写的
	bzero(&(server_addr.sin_zero),8);
    if(connect(sock_fd,(struct sockaddr *)&server_addr,sizeof(struct sockaddr))==-1)
   	{
		printf("connect  fail\r\n");
 		exit(1);
	}
	
     pthread_create(&id1,NULL,(void *)test,(void *)&sock_fd);
	 pthread_join(id1,NULL);
	
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值