您的位置:首页 > 理论基础 > 计算机网络

TCP socket

2016-05-06 17:34 459 查看
socket之TCP

什么是socket?

说道socket,就得说到客户端和服务端。通俗点讲,客户端是指就在我们旁边的,我们需要通过客户端去访问服务端,

做一些数据互动,起到通讯的作用。而服务端则是“远在天边”,但通过建立socket,我们也可以触碰到它。socket

的作用则是为客户端和服务端提供一个用于通讯的接口,通过这个接口,客户端可以和服务端进行通讯。

如何创建一个TCP 通讯?

要建立一个TCP通讯,首先得有客户端和服务端这两个需要通讯的东东,不然谈何通讯。

①创建一个客户端socket

 

 

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>

/* 服务器程序监听的端口号 */
#define PORT 4000

/* 我们一次所能够接收的最大字节数 */
#define MAXDATASIZE 100

int main(int argc, char *argv[])
{
/* 套接字描述符 */
int sockfd, numbytes;

char buf[MAXDATASIZE];

struct hostent *he;

/* 连接者的主机信息 */
struct sockaddr_in their_addr;

/* 检查参数信息,如果执行程序的时候,没有给出参数 */
if (argc != 2)
{
/* 如果没有参数,则给出使用方法后退出 */
fprintf(stderr,“usage: client hostname\n”);
exit(1);
}

/* 取得主机信息 */
if ((he=gethostbyname(argv[1])) == NULL)
/* 如果gethostbyname()发生错误,则显示错误信息并退出 */
herror(“gethostbyname”);
exit(1);
}

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
/* 如果socket()调用出现错误则显示错误信息并退出 */
perror(“socket”);
exit(1);
}

/* 主机字节顺序 */
their_addr.sin_family = AF_INET;

/* 网络字节顺序,短整型 */
their_addr.sin_port = htons(PORT);
their_addr.sin_addr = *((struct in_addr *)he->h_addr);

/* 将结构剩下的部分清零*/
bzero(&(their_addr.sin_zero), 8);

if(connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1)
{
/* 如果connect()建立连接错误,则显示出错误信息,退出 */
perror(“connect”);
exit(1);
}

if((numbytes=recv(sockfd, buf, MAXDATASIZE, 0)) == -1)
{
/* 如果接收数据错误,则显示错误信息并退出 */
perror(“recv”);
exit(1);
}

buf[numbytes] = ‘\0’;
printf(“Received: %s”,buf);
close(sockfd);
return 0;
}


②创建一个socket服务端

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>

/* 服务器要监听的本地端口 */

#define MYPORT 4000

/* 能够同时接受多少没有accept 的连接 */

#define BACKLOG 10

main()
{
/* 在sock_fd 上进行监听,new_fd 接受新的连接 */
int sock_fd, new_fd ;

/* 自己的地址信息 */
struct sockaddr_in my_addr;

/* 连接者的地址信息*/
struct sockaddr_in their_addr;

int sin_size;

/* 如果调用socket() 出错,则返回 */
if ((sockfd =socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
/* 输出错误提示并退出 */
perror(“socket”);
exit(1);
}

/* 主机字节顺序 */
my_addr.sin_family = AF_INET;

/* 网络字节顺序,短整型 */
my_addr.sin_port = htons(MYPORT);

/* 将运行程序机器的IP 填充入s_addr */
my_addr.sin_addr.s_addr = INADDR_ANY;

/* 将此结构的其余空间清零 */
bzero(&(my_addr.sin_zero), 8);

/* 如果该socket句柄绑定服务端的地址失败,则返回 */
if (bind(sockfd, (struct sockaddr *)&my_addr,
sizeof(struct sockaddr)) == -1)
{
/* 如果调用bind()失败,则给出错误提示,退出 */
perror(“bind”);
exit(1);
}

/* 在该服务器地址下的端口监听,若失败,则返回 */
if (listen(sockfd, BACKLOG) == -1)
{
/* 如果调用listen 失败,则给出错误提示,退出 */
perror(“listen failed”);
exit(1);
}

while(1)
{
/* 这里是主accept()循环 */
sin_size = sizeof(struct sockaddr_in);

/* 接受连接,若失败,则返回 */
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1)
{

/* 如果调用accept()出现错误,则给出错误提示,进入下一个循环 */
perror(“accept”);
continue;
}

/* 服务器给出出现连接的信息 */
printf(“server: got connection from %s\n”, inet_ntoa(their_addr.sin_addr));

/* 这里将建立一个子进程来和刚刚建立的套接字进行通讯 */
if (!fork())

/* 这里是子进程 */
/* 这里就是我们说的错误检查! */
if (send(new_fd, “Hello, world!\n”, 14, 0) == -1)
{
/* 如果错误,则给出错误提示,然后关闭这个新连接,退出 */
perror(“send”);
close(new_fd);
exit(0);
}

/* 关闭new_fd 代表的这个套接字连接 */
close(new_fd);
}
}

/* 等待所有的子进程都退出 */
while(waitpid(-1,NULL,WNOHANG) > 0);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息