socket编程实践--壹

    我也是最近接触到了socket编程,觉得知识点有点多,所以想先记录下来,以便之后的复习与警示。这个是socket编程第一篇,主要是基础知识,大佬就不用往下看了,之后的相关文章倒是可以看看!
    这个是Unix/Linux上面的一句话:“管道使的进程向其他进程发送数据就像发送文件一样容易,但是管道具有两个重大的缺陷。管道在一个进程中被创建,通过fork实现共享。因此,管道只能连接两个相关的进程,也只能连上同一台主机上面的进程。Unix提供了另外一种进程间通信的机制——socket。”这里所说的两个缺点应该是:(1):数据仅仅只能在一个方向上流动;(2):仅仅只能在具有公共祖先的两个进程间使用。但是第二个缺点在FIFO就解决了。

  • 流socket
        该socket遵循TCP协议。然后如何实现这个连接也是有一定的步骤的。首先讲服务器端的实现:
        第一步:向内核申请一个socket。这里对于遵循TCP的固定写法就是:int sock_id=socket(PF_INET,SOCK_STREAM,0);注意这个socket的第二个参数,这个和遵循UDP协议的是不一样的。
        第二步:绑定地址到socket上面,包括主机和端口。这里使用的函数是bind(int socket_id,struct sockaddr *addrp,socket_t addrlen);其中要一些点一定的强调一下。可以看到这个第二个参数是struct sockaddr * 的,但是我们在实际的编程中使用了的都是这样一个结构体:struct sockaddr_in。至于它们之间的区别,以及联系,我觉得是要弄清楚的。但是这样说起来就比较多了,所以这里可以去看这篇博主的文章:https://blog.csdn.net/ZWE7616175/article/details/80252048
    我觉得写的可以的,很细,容易理解。我之后也可能会写一下这方面的文章,来巩固自己的知识。当然这里的“坑”肯定不止这样一个。在这一阶段,主要就是几个参数的赋值:
    strcut sockaddr_in saddr;
    saddr.sin_family=AF_INET;
    saddr.sin_port=htons(port);这里的htons使用来将其转化为网络字节顺序的。但是如果你一开始使用的是一个char *p的方式来保存端口号,那么你还的首先将char *p转化为整型,使用atoi()函数,port=atoi§;
    还有一个saddr中sin_addr地址的赋值就有很多方式了,如果你采用的是通过主机名来获取IP地址的话,使用到的函数就会有:
    srtuct hostent *hp=gethostname(hostname);
    bcopy((void )hp->h_addr,(void)&saddr.sin_addr,hp->length);
    但是你如果直接传一个ip地址(char *的形式)过来,对于saddr中的变量sin_addr就得这样去做: saddr.sin_addr.s_addr = inet_addr(ip);(将字符串转换为in_addr类型)我这里说的ip就是你传过来的,例如:“127.0.0.1”,"192.168.140,129"等等 (但是这里如果在虚拟机上实现时我的没有成功。具体原因没有找到,找到后继续补充。)
           第三步:在socket上面允许接入呼叫并设置队列长度。这里使用listen()函数
           第四步: 等待呼叫(也就是客户端的请求)。这里使用的是accept函数。这个是一个阻塞函数。也就是说,如果你想要实现多个客户端的连接的话,可不能仅仅所有的相关代码放在for循环中就可以了。你的使用多进程或者多线程来解决这个问题。当然,你也可以直接让所有应该会连接的客户端连接完成后再去进行通信。注意到accept()函数的返回值是一个文件描述符,所以,之后服务器想和客户端进行通信使用的就是这个文件描述符。(这里也提供了一个思路,如果你想要做一个多人通信的程序,不就可以把accept()返回值都保存下来,之后不就是想和谁通信就和谁通信。还有注意一点,我之前是使用一个数组将其保存,但是今天再看一个bt程序的时候,他给了启发,我觉得可以用一个结构体将其封装,然后将所有accept()的值先封装为结构体,然后用链表串起来)
              这里再简单说一哈客户端的连接注意问题。
              注意点一: 在客户端的代码中,没有说一定要将其socket绑定一个地址,也就是说,客户端不一定要使用bind函数。如果没有绑定地址,在使用connect()函数连接的时候,系统会给调用者一个默认的地址。
              注意点二: 在使用connect()函数的时候,该进程会处于阻塞状态。因为这里涉及到TCP建立连接的三次握手。因为我还没有学习过计算机网络,所以这里就不多说了。之后知识储备够了,再来完善。

猜你喜欢

转载自blog.csdn.net/suliangkuanjiayou/article/details/88633100