多线程 TCP server && client

创建一个TCP Server的连接需要以下几步:

一、服务器端

  • socket:创建服务器监听套接字
  • bind:绑定服务器监听信息到套接字上
  • listen: 开始监听,接收客户端的TCP连接
  • accept:从listen所维护的队列中取出一条已连接的TCP,返回该连接的socket描述字
  • 服务器客户端在连接socket描述字上进行消息通信
  • close:关闭打开着的套接字

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <pthread.h>

#define C_DEFAULT_PORT 8008 //默认端口
#define C_BUFFER_SIZE 1024	//缓存buffer大小


void *recv_pthread(void * v_new_sock)
{
    int sock = *(int *)v_new_sock;
    char back_buf[C_BUFFER_SIZE];
    char Child_buf[C_BUFFER_SIZE];
    while (1)
    {
        memset(back_buf, '\0', C_BUFFER_SIZE);
        memset(Child_buf, '\0', C_BUFFER_SIZE);
        int get_size = recv(sock, Child_buf, sizeof(Child_buf), 0);
        
        if (get_size == -1)
        {
            perror("recv失败");
        }
        else if (get_size == 0)
        {
            printf("用户sock=%d已下线,将退出子程序\n",sock);
            return (void *)0;
        }
        else{
            printf("收到来自sock=%d消息:%s\n",sock ,Child_buf);
            
            strcat(back_buf,"服务器收到了\0");
            strcat(back_buf,Child_buf);

            send(sock, back_buf, sizeof(back_buf), 0);
        }
            
    }
}
int main()
{
	int port = C_DEFAULT_PORT;

	//创建Socket
	int C_sock = socket(PF_INET, SOCK_STREAM, 0);
	if (C_sock == -1)
	{
		perror("Socket建立失败");
		return 1;
	}
	else
		printf("Socket建立成功\n");

	//create socket address and initialize
	struct sockaddr_in bind_addr;
	memset(&bind_addr, 0, sizeof(bind_addr));
	bind_addr.sin_family = AF_INET;//地址族协议ipv4
	bind_addr.sin_addr.s_addr = htonl(INADDR_ANY); //设置接受任意地址
	bind_addr.sin_port = htons(port);			   //将host byte order转换为network byte order

	//bind
	int C_bind = bind(C_sock, (struct sockaddr *)&bind_addr, sizeof(bind_addr));
	if (C_bind == -1)
	{
		perror("bind建立失败");
		return 1;
	}
	else
		printf("bind建立成功\n");

	//listen
	int C_listen = listen(C_sock, 5);
	if (C_listen == -1)
	{
		perror("listen建立失败");
		return 1;
	}
	else
		printf("listen建立成功\n");

	while (1)
	{
		int new_sock = accept(C_sock, NULL, NULL);
		if (new_sock == -1)
		{
			perror("new_sock建立失败");
			return 1;
		}
		else
			printf("\nnew_sock建立成功\n");
       
        pthread_t s_thread,r_thread;
        int r = pthread_create(&r_thread, NULL, recv_pthread, (void *)&new_sock); //独立的线程收消息
        if(r!=0)
            perror("recv_pthread建立失败");
        
       // int s = pthread_create(&s_thread, NULL, send_pthread,  (void *)&new_sock); //独立的线程发消息
       // if(s !=0)
          //  perror("send_pthread建立失败");
       

       //这里join会阻塞
       //pthread_join(s_thread,NULL);
        //pthread_join(r_thread,NULL);
        //close(C_sock);//关闭socket
	    //return 0;
	}
}

二、客户端

  • socket:创建客户端连接套接字
  • connect:向指定服务器发起连接请求
  • 服务器客户端在连接socket描述字上进行消息通信
  • close:关闭打开着的套接字
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/stat.h>
#include <ctype.h>
#include <stdlib.h>
#include <pthread.h>

#define C_DEFAULT_PORT 8008 //默认端口
#define C_BUFFER_SIZE 1024	//缓存buffer大小


void *send_pthread(void * v_new_sock)
{
     int sock = *(int *)v_new_sock;
    char Child_buf[C_BUFFER_SIZE];
    while (1)
    {
        memset(Child_buf, '\0', C_BUFFER_SIZE);
        //printf("发送:");
        scanf("%s", Child_buf);
        int send_size = send(sock, Child_buf, sizeof(Child_buf), 0);
        if (send_size == -1)
        {
            perror("send失败");
        }
    }
}
void *recv_pthread(void * v_new_sock)
{
     int sock = *(int *)v_new_sock;
    char Child_buf[C_BUFFER_SIZE];
    while (1)
    {
        memset(Child_buf, '\0', C_BUFFER_SIZE);
        int get_size = recv(sock, Child_buf, sizeof(Child_buf), 0);
        if (get_size == -1)
        {
            perror("recv失败");
        }
        else if (get_size == 0)
        {
            printf("对方已下线,将退出\n");
            exit(1);
        }
        else
            printf("收到消息:%s\n", Child_buf);
    }
}
int main(void)
{
	
	char ipstr[] = "127.0.0.1"; //这是服务器的地址,使用ifconfig来查看
	printf("请输入待连接的IP,输入0使用默认IP: ");
	char T[100];
	scanf("%s",T);
	if(*(int *)T!=0)
		strcpy(ipstr,T);


	//创建Socket
	int C_sock = socket(AF_INET, SOCK_STREAM, 0);
	if (C_sock == -1)
	{
		perror("Socket建立失败");
		return 1;
	}
	else
		printf("Socket建立成功\n");

	//初始化服务器地址
	struct sockaddr_in server_addr;
	bzero(&server_addr, sizeof(server_addr));
	server_addr.sin_family = AF_INET; //地址族协议ipv4
	inet_pton(AF_INET, ipstr, &server_addr.sin_addr.s_addr);
	server_addr.sin_port = htons(C_DEFAULT_PORT);

	//链接服务器
	int C_con = connect(C_sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
	if (C_con == -1)
	{
		perror("connect建立失败");
        return 1;
    }
    else
        printf("connect建立成功\n");

    printf("\t可以开始聊天了:\n\n");
    
    pthread_t s_thread,r_thread;
    int s = pthread_create(&s_thread, NULL, send_pthread,  (void *)&C_sock); //独立的线程发消息
    if (s !=0)
        perror("send_pthread建立失败");
    
    int r = pthread_create(&r_thread, NULL, recv_pthread,  (void *)&C_sock); //独立的线程收消息
    if (r !=0)
        perror("recv_pthread建立失败");
   

    pthread_join(s_thread,NULL);
    pthread_join(r_thread,NULL);
    close(C_sock);//关闭socket
    return 0;
}


posted @ 2022-03-05 16:00  Cheney822  阅读(56)  评论(0编辑  收藏  举报