日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

方案一TCP 完成聊天室的编写

發布時間:2025/3/19 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 方案一TCP 完成聊天室的编写 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

完成聊天室 需要聊天 那就要建立連接?建立連接后 就發送信息

建立連接 和 發送信息 需要什么函數??

服務器 客戶端 各自需要什么?

服務器:

1.1 ?socket :創建一個Socket 用以監聽 (一個空的通道 ?一頭將要連服務器 一頭將要連客戶)

1.2 ?Bind :綁定 IP 和 端口號

1.3 ?Listen :監聽 ?兩個參數 ?參數1 :socket 那個通道

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 參數2 :數字 ?監聽隊列的大小 : 同一時刻 允許的最大連接數

?

1.4 ?accept :接受客戶發起的連接 ?參數 1 : ?socket

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?參數 2 :客戶端的IP 和端口...

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?參數 3 :結構體的長度

?

1.5 ?send 和 recv

客戶端:

2.1 ?socket : 創建一個socket

2.2 ?connect : 連接

?

具體函數都可以利用man (manual)手冊進行查詢 :例如man 2 socket 記得把其中的頭文件加入自己的代碼中

標準的man手冊主要分為8個章節,分別為:

1 User Commands // 用戶命令

2 System Calls // 系統調用

3 C Library Functions // C函數庫調用

4 Devices and Special Files // 設備文件和特殊文件

5 File Formats and Conventions // 配置文件及格式

6 Games et. Al. // 游戲

7 Miscellanea // 雜項

8 System Administration tools and Deamons // 管理類命令

使用格式:

man [章節] COMMAND

q Q ZZ 退出

?

基本的函數

TCPserver.c :

?

1.1 ?Socket

創建一個int 型socketid接socket的返回值 返回值是一個文件描述符

一般的,文件描述符: 0 標準輸入 1 標準輸出 2 標準錯誤輸出

0、1、2是整數表示的,對應的FILE *結構的表示就是stdin、stdout、stderr,

0就是stdin,1就是stdout,2就是stderr

(函數原型)int socket(int domain, int type, int protocol);

Domain: 地址族協議 我們一般用PF_INET (ipv4協議)

Type: 套接字的類型 (TCP用SOCK_STREAM)(UDP用 SOCK_DGRAM)

前面博客中已經告知所有相關知識點

Protocol: 一般默認為0 這個參數是由前面兩個就決定好的 不需要特意再去指定

?

?

1.2 ?Bind

創建一個int型 ret 接bind的返回值 返回值 代表是否綁定成功

(函數原型)int bind ( int ?sockfd, ?const ?struct ?sockaddr ?*my_addr, ?socklen_t addrlen);

Sockfd: 文件描述符 指定綁定誰 (在服務器創建了socket之后當然先把自己綁在通道的一端,等待客戶向自己發起連接)

my_addr: 是一個結構體:struct ?sockaddr

Addrlen: 是第二個參數 結構體的大小

?

**所以在第二個參數這里 我們就需要在開始bind前創建一個結構體

Struct ??sockaddr_in ??server_addr;

并且對這個結構體 內部的數據 進行初始化

memset(&server_addr, 0, sizeof(struct sockaddr_in)); //清空原始數據 防止出錯(這個函數需要+string.h頭文件)

server_addr.sin_family = AF_INET; //地址族協議 用ipv4

server_addr.sin_port = PORT; //指定端口號 PORT自己在最開始指定(我是8888)

server_addr.sin_addr.s_addr =?inet_addr("192.168.222.128");

//指定服務器的ip地址為 192.168.222.128

//這里 因為系統內存放的數據是二進制(長整型)所以用到轉換函數 inet_addr( )

//函數原型in_addr_t inet_addr(const char* strptr);

//返回:若字符串有效則將字符串轉換為32位二進制網絡字節序的IPV4地址

?

?

1.3 ?Listen

創建一個int型 ret 接Listen的返回值 返回值 代表是否綁定成功

(函數原型)int listen(int sockfd, int backlog);

Sockfd: 監聽服務器創建的通道上是否有請求

Backlog: 同一時刻 允許的最大連接數

?

?

1.4 ?Accept

創建一個int型 fd [ i ] ?接Listen的返回值 返回值 代表接受到哪個客戶端發送來的請求

//fd [ i ] 因為你接受到的客戶請求可能不止一個 你需要把他們都記下來 一個個處理

//但是fd [ i ] 的值是從4開始的 前面說過了 012 標準--輸入、輸出、錯誤輸出 3 是自己創建的sockfd

(函數原型)int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

Sockfd: 文件描述符 指示哪個客戶的文件描述符有變化

ddr: 是一個結構體:struct ?sockaddr 代表接受到的 客戶的地址

Addrlen: 是第二個參數 結構體的大小

?

**所以在第二個參數這里 我們同樣要在開始前創建一個結構體

Struct ??sockaddr_in ??client_addr;

memset(&server_addr, 0, sizeof(struct sockaddr_in)); //清空原始數據 防止出錯

?

?

1.5 ?創建線程pthread_create

創建一個int型 ret接pthread_create的返回值 返回值 代表線程是否創建成功

(函數原型)int pthread_create(pthread_t *restrict thread,

?????????????? const pthread_attr_t *restrict attr,

?????????????? void *(*start_routine)(void*), void *restrict arg);

restrict thread:開始就創建一個pthread_t tid[100]; 用以創建線程 因為一次接受就需要一次線程的創建;

restrict attr: 用于指定各種不同的線程屬性,默認為NULL

*(*start_routine)(void*): 線程創建后 用此處對應的函數 進行線程的處理(完成此線程需要的功能)

restrict arg: &fd[ i ] ?: 最后一個參數是運行函數的參數 哪個客戶調用這個函數了

?

?

TCPclient.c

2.1 soket()

同上面服務器的一樣

2.2 connect()

(函數原型)int ?connect(int ?sockfd, ?const ?struct sockaddr *serv_addr, socklen_t ?addrlen);

Socket:?很明顯和上面差不多 這里的sockfd就是客戶自己創建的

serv_addr:?和上面一樣 自己一開始就創建一個結構體就行 記得也要初始化

Addrlen:?大小就是結構體的大小

?

?

最后就是寫一個 send 一個recv 函數用以接收和發送信息了。

?

TCPserver.c

#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <stdlib.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #include <pthread.h>#define PORT 8888struct info {char buf[100];int to_fd; }; struct info SendBuf;void *HandlerClientThread(void *arg) {int ret;while (1){ret = recv(*(int *)arg, &SendBuf, sizeof(SendBuf), 0);if (-1 == ret){perror("recv");return;}//printf("Receive From %d : %s\n", *(int *)arg, buf);ret = send(SendBuf.to_fd, &SendBuf, sizeof(SendBuf), 0);if (-1 == ret){perror("send");return;}memset(&SendBuf, 0, sizeof(SendBuf));}}int main() {int sockfd, ret, fd[100] = {0}, length, i = 0;struct sockaddr_in server_addr;struct sockaddr_in client_addr;char buf[100] = {0};pthread_t tid[100];printf("START SERVER!\n");sockfd = socket(PF_INET, SOCK_STREAM, 0);if (-1 == sockfd){perror("sockfd");exit(1);}int opt = 1;setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));memset(&server_addr, 0, sizeof(struct sockaddr_in));server_addr.sin_family = AF_INET;server_addr.sin_port = PORT; // server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");server_addr.sin_addr.s_addr = inet_addr("192.168.222.128");ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));if (-1 == ret){perror("bind");exit(1);}printf("WAITTING FOR CONNECT...\n");while(1){ret = listen(sockfd, 5);if (-1 == ret){perror("listen");exit(1);}length = sizeof(client_addr);fd[i] = accept(sockfd, (struct sockaddr *)&client_addr, &length);if (-1 == fd[i]){perror("accept");exit(1);}printf("ACCEPT %d ,Port = %d!\n", fd[i], client_addr.sin_port);ret = pthread_create(&tid[i], NULL, HandlerClientThread, (void *)&fd[i]);if (0 != ret){perror("create");exit(1);}i++;}return 0; }

TCPclient.c

#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <stdlib.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #include <pthread.h>#define PORT 8888struct info {char buf[100];int to_fd; };struct info SendBuf;void *MyReceive(void *arg) {int ret;while (1){ret = recv(*(int *)arg, &SendBuf, sizeof(SendBuf), 0);if (-1 == ret){perror("recv");return;}printf("\t\t\t%s\n", SendBuf.buf);memset(&SendBuf, 0, sizeof(SendBuf));} }//int main() int main(int argc, char *argv[]) {int sockfd, ret;struct sockaddr_in server_addr;char buf[100] = {0};pthread_t tid;sockfd = socket(PF_INET, SOCK_STREAM, 0);if (-1 == sockfd){perror("socket");exit(1);}memset(&server_addr, 0, sizeof(struct sockaddr_in));server_addr.sin_family = AF_INET;server_addr.sin_port = PORT; // server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");server_addr.sin_addr.s_addr = inet_addr(argv[1]);//自己從運行程序的時候傳進來ret = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));if (-1 == ret){perror("connect");exit(1);}ret = pthread_create(&tid, NULL, MyReceive, (void *)&sockfd);if (0 != ret){perror("create");exit(1);} while(1){scanf("%s %d", SendBuf.buf, &SendBuf.to_fd);ret = send(sockfd, &SendBuf, sizeof(SendBuf), 0);if (-1 == ret){perror("sand");exit(1);}}return 0; }

?

總結

以上是生活随笔為你收集整理的方案一TCP 完成聊天室的编写的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。