socket编程用线程实现TCP协议通信

函数介绍:       
int socket(int domain, int type, int protocol);

DESCRIPTION
       socket() creates an endpoint for communication and returns a descriptor.

 Name                Purpose                          Man page
       AF_UNIX, AF_LOCAL   Local communication              unix(7)
       AF_INET             IPv4 Internet protocols          ip(7)
       AF_INET6            IPv6 Internet protocols          ipv6(7)
       AF_IPX              IPX - Novell protocols
       AF_NETLINK          Kernel user interface device     netlink(7)
       AF_X25              ITU-T X.25 / ISO-8208 protocol   x25(7)
       AF_AX25             Amateur radio AX.25 protocol
       AF_ATMPVC           Access to raw ATM PVCs
       AF_APPLETALK        Appletalk                        ddp(7)
       AF_PACKET           Low level packet interface       packet(7)

RETURN VALUE
       On  success,  a  file  descriptor for the new socket is returned.  On error, -1 is
       returned, and errno is set appropriately.


在linux环境下,结构体struct sockaddr_in在/usr/include/netinet/in.h中定义,具体如下:
/* Structure describing an Internet socket address. */
struct sockaddr_in
{
    __SOCKADDR_COMMON (sin_);
    in_port_t sin_port;                     /* Port number. */
    struct in_addr sin_addr;            /* Internet address. */

    /* Pad to size of `struct sockaddr'. */
    unsigned char sin_zero[sizeof (struct sockaddr) -
                           __SOCKADDR_COMMON_SIZE -
                           sizeof (in_port_t) -
                           sizeof (struct in_addr)];    
                           /* 字符数组sin_zero[8]的存在是为了保证结构体struct sockaddr_in的大小和结构体struct sockaddr的大小相等 */
};
struct sockaddr是通用的套接字地址,而struct sockaddr_in则是internet环境下套接字的地址形式,二者长度一样,都是16个字节。二者是并列结构,指向sockaddr_in结构的指针也可以指向sockaddr。一般情况下,需要把sockaddr_in结构强制转换成sockaddr结构再传入系统调用函数中。

connect函数介绍:
 int connect(int sockfd, const struct sockaddr *addr,
                   socklen_t addrlen);

DESCRIPTION
       The  connect()  system call connects the socket referred to by the file descriptor
       sockfd to the address specified by addr.  The addrlen argument specifies the  size
       of  addr.  The format of the address in addr is determined by the address space of
       the socket sockfd; see socket(2) for further details.

       If the socket sockfd is of type SOCK_DGRAM then addr is the address to which data-
       grams are sent by default, and the only address from which datagrams are received.
       If the socket is of type SOCK_STREAM or SOCK_SEQPACKET, this call attempts to make
       a connection to the socket that is bound to the address specified by addr.

RETURN VALUE
       If  the  connection  or  binding  succeeds,  zero  is  returned.   On error, -1 is

       returned, and errno is set appropriately.

注意:在编译的时候要加-pthread选项



客户端:


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

static usage(const char* proc)
{
    printf("usage:%s[ip][port]\n",proc);
}

int main(int argc,char* argv[])
{
    if(argc!=3)
    {
        usage(argv[0]);
        exit(1);
    }
    int sock=socket(AF_INET,SOCK_STREAM,0);
    if(sock<0)
    {
        perror("socket");
        return 2;
    }

    struct sockaddr_in remote;
    remote.sin_family=AF_INET;
    remote.sin_port=htons(atoi(argv[2]));
    remote.sin_addr.s_addr=inet_addr(argv[1]);

    if(connect(sock,(struct sockaddr*)&remote,sizeof(remote))<0)
    {
        perror("connect");
        return 3;
    }

    char buf[1024];
    while(1)
    {
        memset(buf,'\0',sizeof(buf));
        printf("please enter:");
        fflush(stdout);
        ssize_t _s=read(0,buf,sizeof(buf)-1);
        if(_s>0)
        {
            buf[_s-1]='\0';
            write(sock,buf,strlen(buf));
            _s=read(sock,buf,sizeof(buf));
            if(_s>0)
            {
                buf[_s]='\0';
                printf("%s\n",buf);
            }
        }
    }
    return 0;
}


服务器端:

#include<stdlib.h>
#include<unistd.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<pthread.h>
#include<arpa/inet.h>
#include<sys/socket.h>

static void usage(const char *proc)
{
	printf("usage:%s[ip][port]\n",proc);
}

void *thread_run(void *arg)
{
	printf("create a new thread\n");
	int fd=(int)arg;
	char buf[1024];
	while(1)
	{
		memset(buf,'\0',sizeof(buf));
		size_t _s =read(fd,buf,sizeof(buf)-1);
		if(_s>0)
		{
			buf[_s]='\0';
			printf("client:%s\n",buf);
			write(fd,buf,strlen(buf));
		}
		else if(_s==0)
		{
			printf("client close...\n");
			break;
		}
		else
		{
			printf("read error...\n");
			break;
		}
	}
	return (void*)0;
}
int main(int argc,char *argv[])
{
	if(argc!=3)
	{
		usage(argv[0]);
		exit(1);
	}

	//create sock
	int listen_sock=socket(AF_INET,SOCK_STREAM,0);
	if(listen_sock<0)
	{
        printf("create error,errno:%d  %s\n",errno,strerror(errno));
	}
    struct sockaddr_in local;
	local.sin_family=AF_INET;
	local.sin_port=htons(atoi(argv[2]));
	local.sin_addr.s_addr=inet_addr(argv[1]);

	//bind
	if(bind(listen_sock,(struct sockaddr*)&local,sizeof(local))<0)
	{
		perror("bind");
		return 2;
	}

	//listen
	listen(listen_sock,5);

	//accept
	struct sockaddr_in peer;
	socklen_t len=sizeof(peer);
	while(1)
	{
		int fd=accept(listen_sock,(struct sockaddr*)&peer,&len);
		if(fd<0)
		{
			perror("accept");
			return 3;
		}
		printf("get a new link,socket -> %s:%d\n",inet_ntoa(peer.sin_addr),ntohs(peer.sin_port));
		pthread_t id;
		pthread_create(&id,NULL,thread_run,(void*)fd);
		pthread_detach(id);
	}

	return 0;
}





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值